diff --git a/.lintstagedrc.js b/.lintstagedrc.js deleted file mode 100644 index 7aa92425df..0000000000 --- a/.lintstagedrc.js +++ /dev/null @@ -1,10 +0,0 @@ -const path = require("path"); - -const buildEslintCommand = (filenames) => - `eslint --fix ${filenames - .map((f) => path.relative(process.cwd(), f)) - .join(" ")}`; - -module.exports = { - "*.{ts,tsx}": [buildEslintCommand, "prettier --write"], -}; diff --git a/.prettierignore b/.prettierignore index 603e2fc64e..580ca4f287 100644 --- a/.prettierignore +++ b/.prettierignore @@ -4,3 +4,10 @@ node_modules jest-coverage web-build mobile-app/coverage +.husky +.idea +.vscode +.contented +dist +package-lock.json +pnpm-lock.yaml \ No newline at end of file diff --git a/mobile-app/app/api/transaction/dfi_converter.ts b/mobile-app/app/api/transaction/dfi_converter.ts index ab2b10648a..966138cf78 100644 --- a/mobile-app/app/api/transaction/dfi_converter.ts +++ b/mobile-app/app/api/transaction/dfi_converter.ts @@ -1,6 +1,6 @@ import { translate } from "@translations"; import BigNumber from "bignumber.js"; -import { DfTxSigner } from "@waveshq/walletkit-ui/dist/store"; +import { DfTxSigner } from "@waveshq/walletkit-ui/store"; import { WhaleWalletAccount } from "@defichain/whale-api-wallet"; import { CTransactionSegWit, diff --git a/mobile-app/app/api/transaction/transfer_domain.ts b/mobile-app/app/api/transaction/transfer_domain.ts index 0eced51a21..b684768eed 100644 --- a/mobile-app/app/api/transaction/transfer_domain.ts +++ b/mobile-app/app/api/transaction/transfer_domain.ts @@ -1,7 +1,7 @@ import { translate } from "@translations"; import BigNumber from "bignumber.js"; import { ethers, providers, utils } from "ethers"; -import { DfTxSigner } from "@waveshq/walletkit-ui/dist/store"; +import { DfTxSigner } from "@waveshq/walletkit-ui/store"; import { WhaleWalletAccount } from "@defichain/whale-api-wallet"; import { CTransactionSegWit, diff --git a/mobile-app/app/components/ConfirmSummaryTitle.tsx b/mobile-app/app/components/ConfirmSummaryTitle.tsx index 90b97efd61..8b5cfcd8e3 100644 --- a/mobile-app/app/components/ConfirmSummaryTitle.tsx +++ b/mobile-app/app/components/ConfirmSummaryTitle.tsx @@ -4,7 +4,7 @@ import { tailwind } from "@tailwind"; import { getNativeIcon } from "@components/icons/assets"; import { translate } from "@translations"; import { RandomAvatar } from "@screens/AppNavigator/screens/Portfolio/components/RandomAvatar"; -import { AddressType } from "@waveshq/walletkit-ui/dist/store"; +import { AddressType } from "@waveshq/walletkit-ui/store"; import { View } from "react-native"; import { ThemedTextV2, ThemedViewV2 } from "./themed"; @@ -25,7 +25,7 @@ interface ConfirmSummaryTitleV2Props { } export function ConfirmSummaryTitle( - props: ConfirmSummaryTitleV2Props + props: ConfirmSummaryTitleV2Props, ): JSX.Element { const IconA = getNativeIcon(props.iconA); const IconB = getNativeIcon(props.iconB); @@ -85,7 +85,7 @@ export function ConfirmSummaryTitle( {translate( "screens/ConfirmCompositeSwapScreen", "Settlement value {{percentageChange}}", - { percentageChange: props.oraclePrice } + { percentageChange: props.oraclePrice }, )} @@ -95,7 +95,7 @@ export function ConfirmSummaryTitle( renderText={(value) => ( @@ -121,7 +121,7 @@ export function ConfirmSummaryTitle( dark={tailwind("bg-mono-dark-v2-200")} light={tailwind("bg-mono-light-v2-200")} style={tailwind( - "rounded-full pl-1 pr-2.5 py-1 flex flex-row items-center overflow-hidden ml-2" + "rounded-full pl-1 pr-2.5 py-1 flex flex-row items-center overflow-hidden ml-2", )} > @@ -163,7 +163,7 @@ export function ConfirmSummaryTitle( { "pl-1": props.addressType === AddressType.WalletAddress, "pl-2.5": props.addressType !== AddressType.WalletAddress, - } + }, )} > {props.addressType === AddressType.WalletAddress && ( diff --git a/mobile-app/app/components/HeaderTitle.test.tsx b/mobile-app/app/components/HeaderTitle.test.tsx index 4f794d6ab0..9604366a98 100644 --- a/mobile-app/app/components/HeaderTitle.test.tsx +++ b/mobile-app/app/components/HeaderTitle.test.tsx @@ -2,7 +2,7 @@ import { configureStore } from "@reduxjs/toolkit"; import { Provider } from "react-redux"; import { render } from "@testing-library/react-native"; import { RootState } from "@store"; -import { block } from "@waveshq/walletkit-ui/dist/store/block"; +import { block } from "@waveshq/walletkit-ui/store/block"; import { HeaderTitle } from "./HeaderTitle"; jest.mock("@contexts/CustomServiceProvider"); diff --git a/mobile-app/app/components/OceanInterface/OceanInterface.tsx b/mobile-app/app/components/OceanInterface/OceanInterface.tsx index dcbcea21e3..a3d3ad529e 100644 --- a/mobile-app/app/components/OceanInterface/OceanInterface.tsx +++ b/mobile-app/app/components/OceanInterface/OceanInterface.tsx @@ -6,7 +6,7 @@ import { useWalletContext } from "@shared-contexts/WalletContext"; import { useNetworkContext, useWhaleApiClient, -} from "@waveshq/walletkit-ui/dist/contexts"; +} from "@waveshq/walletkit-ui/contexts"; import { CTransactionSegWit } from "@defichain/jellyfish-transaction/dist"; import { WhaleApiClient } from "@defichain/whale-api-client"; import { Transaction } from "@defichain/whale-api-client/dist/api/transactions"; @@ -17,7 +17,7 @@ import { ocean, OceanTransaction, TransactionStatusCode, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { tailwind } from "@tailwind"; import { translate } from "@translations"; import { useCallback, useEffect, useRef, useState } from "react"; diff --git a/mobile-app/app/components/OceanInterface/TransactionDetail.tsx b/mobile-app/app/components/OceanInterface/TransactionDetail.tsx index b31a495252..d2afe714ae 100644 --- a/mobile-app/app/components/OceanInterface/TransactionDetail.tsx +++ b/mobile-app/app/components/OceanInterface/TransactionDetail.tsx @@ -8,7 +8,7 @@ import { ThemedTextV2, ThemedViewV2, } from "@components/themed"; -import { TransactionStatusCode } from "@waveshq/walletkit-ui/dist/store"; +import { TransactionStatusCode } from "@waveshq/walletkit-ui/store"; import { TransactionCloseButton } from "./TransactionCloseButton"; import { TransactionIDButton } from "./TransactionIDButton"; diff --git a/mobile-app/app/components/SummaryTitle.tsx b/mobile-app/app/components/SummaryTitle.tsx index 05af981acd..c0f947dc1c 100644 --- a/mobile-app/app/components/SummaryTitle.tsx +++ b/mobile-app/app/components/SummaryTitle.tsx @@ -4,7 +4,7 @@ import { tailwind } from "@tailwind"; import { getNativeIcon } from "@components/icons/assets"; import { translate } from "@translations"; import { RandomAvatar } from "@screens/AppNavigator/screens/Portfolio/components/RandomAvatar"; -import { AddressType } from "@waveshq/walletkit-ui/dist/store"; +import { AddressType } from "@waveshq/walletkit-ui/store"; import { LocalAddress, WhitelistedAddress } from "@store/userPreferences"; import { DomainType } from "@contexts/DomainContext"; diff --git a/mobile-app/app/components/icons/assets/_Default.tsx b/mobile-app/app/components/icons/assets/_Default.tsx index 04604ef72b..6edfbc1561 100644 --- a/mobile-app/app/components/icons/assets/_Default.tsx +++ b/mobile-app/app/components/icons/assets/_Default.tsx @@ -1,5 +1,5 @@ import { RootState } from "@store"; -import { tokenSelectorByDisplaySymbol } from "@waveshq/walletkit-ui/dist/store"; +import { tokenSelectorByDisplaySymbol } from "@waveshq/walletkit-ui/store"; import { SvgProps } from "react-native-svg"; import { useSelector } from "react-redux"; import { DefaultLoanToken } from "./DefaultLoanToken"; @@ -8,7 +8,7 @@ import { DefaultToken } from "./DefaultToken"; export function _Default(symbol: string): (props: SvgProps) => JSX.Element { const tokenDetail = useSelector((state: RootState) => - tokenSelectorByDisplaySymbol(state.wallet, symbol) + tokenSelectorByDisplaySymbol(state.wallet, symbol), ); if (tokenDetail?.isLoanToken) { diff --git a/mobile-app/app/components/icons/assets/index.test.tsx b/mobile-app/app/components/icons/assets/index.test.tsx index 789c63b76a..15360eb7e6 100644 --- a/mobile-app/app/components/icons/assets/index.test.tsx +++ b/mobile-app/app/components/icons/assets/index.test.tsx @@ -1,6 +1,6 @@ import { configureStore } from "@reduxjs/toolkit"; import { RootState } from "@store"; -import { wallet } from "@waveshq/walletkit-ui/dist/store"; +import { wallet } from "@waveshq/walletkit-ui/store"; import { render, RenderAPI } from "@testing-library/react-native"; import { Provider } from "react-redux"; import { AppIcon } from "../AppIcon"; diff --git a/mobile-app/app/contexts/CustomServiceProvider.tsx b/mobile-app/app/contexts/CustomServiceProvider.tsx index f121adbfa0..2c9e0aca90 100644 --- a/mobile-app/app/contexts/CustomServiceProvider.tsx +++ b/mobile-app/app/contexts/CustomServiceProvider.tsx @@ -1,6 +1,6 @@ import { EnvironmentNetwork } from "@waveshq/walletkit-core"; import { useNetworkContext } from "@waveshq/walletkit-ui"; -import { BaseLogger } from "@waveshq/walletkit-ui/dist/contexts/logger"; +import { BaseLogger } from "@waveshq/walletkit-ui/contexts/logger"; import React, { createContext, PropsWithChildren, diff --git a/mobile-app/app/contexts/EVMProvider.tsx b/mobile-app/app/contexts/EVMProvider.tsx index 8a90d54115..626290d03c 100644 --- a/mobile-app/app/contexts/EVMProvider.tsx +++ b/mobile-app/app/contexts/EVMProvider.tsx @@ -7,7 +7,7 @@ import React, { } from "react"; import { providers } from "ethers"; import { useNetworkContext } from "@waveshq/walletkit-ui"; -import { BaseLogger } from "@waveshq/walletkit-ui/dist/contexts/logger"; +import { BaseLogger } from "@waveshq/walletkit-ui/contexts/logger"; import { useCustomServiceProviderContext } from "./CustomServiceProvider"; interface EVMProviderContextI { diff --git a/mobile-app/app/contexts/FeatureFlagContext.tsx b/mobile-app/app/contexts/FeatureFlagContext.tsx index eb2b72f1a6..38237195b1 100644 --- a/mobile-app/app/contexts/FeatureFlagContext.tsx +++ b/mobile-app/app/contexts/FeatureFlagContext.tsx @@ -6,7 +6,7 @@ import { import { useGetFeatureFlagsQuery, usePrefetch, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { nativeApplicationVersion } from "expo-application"; import { createContext, diff --git a/mobile-app/app/hooks/useApiStatus.ts b/mobile-app/app/hooks/useApiStatus.ts index dac837c470..040ebf3a0e 100644 --- a/mobile-app/app/hooks/useApiStatus.ts +++ b/mobile-app/app/hooks/useApiStatus.ts @@ -7,7 +7,7 @@ import dayjs from "dayjs"; import { useGetBlockchainStatusQuery, useGetOceanStatusQuery, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; // MAX_TIME_DIFF set to 45 mins to display warning message (in AnnouncementBanner) when blockchain is down only in Production mode, else 5 seconds for local runs const MAX_TIME_DIFF = getEnvironment(getReleaseChannel()).debug @@ -19,14 +19,14 @@ export function useApiStatus(): { isOceanDown: boolean; } { const { lastSync, lastSuccessfulSync } = useSelector( - (state: RootState) => state.block + (state: RootState) => state.block, ); const { data: blockchainStatus, isSuccess: isBlockchainSuccess } = useGetBlockchainStatusQuery( {}, { pollingInterval: 1000 * 60 * 5, // every 5mins - } + }, ); const { data: oceanStatus, isSuccess: isOceanSuccess } = @@ -37,7 +37,7 @@ export function useApiStatus(): { function getBlockStatus( lastSync?: string, - lastSuccessfulSync?: string + lastSuccessfulSync?: string, ): void { if (lastSync !== undefined && lastSuccessfulSync !== undefined) { // stats api is down - if syncing time is more than MAX_TIME_DIFF - checks which api is down diff --git a/mobile-app/app/hooks/wallet/Conversion.ts b/mobile-app/app/hooks/wallet/Conversion.ts index d0da4047f9..150bf56009 100644 --- a/mobile-app/app/hooks/wallet/Conversion.ts +++ b/mobile-app/app/hooks/wallet/Conversion.ts @@ -7,7 +7,7 @@ import { DFIUtxoSelector, unifiedDFISelector, transactionQueue, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { dfiConversionCrafter } from "@api/transaction/dfi_converter"; import { NativeLoggingProps } from "@shared-contexts/NativeLoggingProvider"; import { ConvertDirection } from "@screens/enum"; diff --git a/mobile-app/app/hooks/wallet/DisplayUtxoWarning.ts b/mobile-app/app/hooks/wallet/DisplayUtxoWarning.ts index a30eaae57c..d4b572d449 100644 --- a/mobile-app/app/hooks/wallet/DisplayUtxoWarning.ts +++ b/mobile-app/app/hooks/wallet/DisplayUtxoWarning.ts @@ -2,22 +2,19 @@ import { useCallback } from "react"; import BigNumber from "bignumber.js"; import { useSelector } from "react-redux"; import { RootState } from "@store"; -import { - DFITokenSelector, - DFIUtxoSelector, -} from "@waveshq/walletkit-ui/dist/store"; +import { DFITokenSelector, DFIUtxoSelector } from "@waveshq/walletkit-ui/store"; export function useDisplayUtxoWarning(): { getDisplayUtxoWarningStatus: ( amountInDFI: BigNumber, - displaySymbol: string + displaySymbol: string, ) => boolean; } { const DFIToken = useSelector((state: RootState) => - DFITokenSelector(state.wallet) + DFITokenSelector(state.wallet), ); const DFIUtxo = useSelector((state: RootState) => - DFIUtxoSelector(state.wallet) + DFIUtxoSelector(state.wallet), ); const reservedDFI = 0.1; @@ -33,13 +30,13 @@ export function useDisplayUtxoWarning(): { const toLessInUtxo = BigNumber.max( new BigNumber(amountInDFI).minus(DFIToken.amount), - 0 + 0, ); return new BigNumber(DFIUtxo.amount) .minus(toLessInUtxo) .isLessThanOrEqualTo(reservedDFI); }, - [DFIToken, DFIUtxo] + [DFIToken, DFIUtxo], ); return { diff --git a/mobile-app/app/screens/AppNavigator/screens/Auctions/AuctionScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Auctions/AuctionScreen.tsx index 88d8591407..99dd686ff4 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Auctions/AuctionScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Auctions/AuctionScreen.tsx @@ -18,7 +18,7 @@ import { } from "@store/auctions"; import { useIsFocused } from "@react-navigation/native"; import { useAppDispatch } from "@hooks/useAppDispatch"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { fetchVaults } from "@store/loans"; import { useWalletContext } from "@shared-contexts/WalletContext"; import { @@ -35,7 +35,7 @@ type Props = StackScreenProps; export function AuctionScreen({ navigation }: Props): JSX.Element { const { hasFetchAuctionsData } = useSelector( - (state: RootState) => state.auctions + (state: RootState) => state.auctions, ); const [showLoader, setShowLoader] = useState(true); const [isFirstLoad, setIsFirstLoad] = useState(false); @@ -45,7 +45,7 @@ export function AuctionScreen({ navigation }: Props): JSX.Element { const [searchString, setSearchString] = useState(""); const [isSearching, setIsSearching] = useState(false); const batches = useSelector((state: RootState) => - getAuctionBatches(state.auctions) + getAuctionBatches(state.auctions), ); const handleFilter = useCallback( debounce((searchString: string) => { @@ -59,20 +59,23 @@ export function AuctionScreen({ navigation }: Props): JSX.Element { .split(" ") .filter((e) => e !== "") .every((i) => - batch.collateralTokenSymbols.join(" ").toLowerCase().includes(i) - ) - ) + batch.collateralTokenSymbols + .join(" ") + .toLowerCase() + .includes(i), + ), + ), ); } else { setFilteredAuctionBatches([]); } }, 500), - [batches] + [batches], ); const [filteredAuctionBatches, setFilteredAuctionBatches] = useState>(batches); const [activeButtonGroup, setActiveButtonGroup] = useState( - ButtonGroupTabKey.AllBids + ButtonGroupTabKey.AllBids, ); const blockCount = useSelector((state: RootState) => state.block.count); @@ -176,7 +179,7 @@ export function AuctionScreen({ navigation }: Props): JSX.Element { }); setFilteredAuctionBatches(filteredAuctions); }, - [batches, address] + [batches, address], ); if (hasFetchAuctionsData && batches?.length === 0 && !showSearchInput) { @@ -212,11 +215,11 @@ export function AuctionScreen({ navigation }: Props): JSX.Element { ? translate( "screens/AuctionScreen", "Search results for “{{input}}”", - { input: searchString?.trim() } + { input: searchString?.trim() }, ) : translate( "screens/AuctionScreen", - "Search for auctions using collateral token names i.e. DFI DUSD dBTC." + "Search for auctions using collateral token names i.e. DFI DUSD dBTC.", )} diff --git a/mobile-app/app/screens/AppNavigator/screens/Auctions/components/BatchCard.test.tsx b/mobile-app/app/screens/AppNavigator/screens/Auctions/components/BatchCard.test.tsx index 8c55ce4788..270ce004cc 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Auctions/components/BatchCard.test.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Auctions/components/BatchCard.test.tsx @@ -2,12 +2,12 @@ import { render } from "@testing-library/react-native"; import { configureStore } from "@reduxjs/toolkit"; import { Provider } from "react-redux"; import { RootState } from "@store"; -import { block } from "@waveshq/walletkit-ui/dist/store/block"; +import { block } from "@waveshq/walletkit-ui/store/block"; import { LoanVaultLiquidated, LoanVaultState, } from "@defichain/whale-api-client/dist/api/loan"; -import { wallet } from "@waveshq/walletkit-ui/dist/store"; +import { wallet } from "@waveshq/walletkit-ui/store"; import BigNumber from "bignumber.js"; import { BatchCard } from "./BatchCard"; @@ -307,7 +307,7 @@ describe("Batch Card", () => { onQuickBid={() => {}} testID="batch_card" /> - + , ); expect(rendered.toJSON()).toMatchSnapshot(); }); diff --git a/mobile-app/app/screens/AppNavigator/screens/Auctions/components/BidCard.test.tsx b/mobile-app/app/screens/AppNavigator/screens/Auctions/components/BidCard.test.tsx index bf52e57b39..44b5fd4a8a 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Auctions/components/BidCard.test.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Auctions/components/BidCard.test.tsx @@ -1,5 +1,5 @@ import { RootState } from "@store"; -import { block } from "@waveshq/walletkit-ui/dist/store/block"; +import { block } from "@waveshq/walletkit-ui/store/block"; import { render } from "@testing-library/react-native"; import { Provider } from "react-redux"; @@ -82,7 +82,7 @@ describe("Bid Card", () => { const rendered = render( - + , ); expect(rendered.toJSON()).toMatchSnapshot(); }); diff --git a/mobile-app/app/screens/AppNavigator/screens/Auctions/components/QuickBid.tsx b/mobile-app/app/screens/AppNavigator/screens/Auctions/components/QuickBid.tsx index 5ac5f573ca..2cb04f2575 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Auctions/components/QuickBid.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Auctions/components/QuickBid.tsx @@ -11,11 +11,11 @@ import { LoanVaultLiquidated } from "@defichain/whale-api-client/dist/api/loan"; import { useSelector } from "react-redux"; import { RootState } from "@store"; import { useLogger } from "@shared-contexts/NativeLoggingProvider"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { NumericFormat as NumberFormat } from "react-number-format"; import { NumberRowV2 } from "@components/NumberRowV2"; import { ButtonV2 } from "@components/ButtonV2"; -import { tokensSelector } from "@waveshq/walletkit-ui/dist/store"; +import { tokensSelector } from "@waveshq/walletkit-ui/store"; import { ScrollView } from "react-native-gesture-handler"; import { useSignBidAndSend } from "../hooks/SignBidAndSend"; import { useAuctionTime } from "../hooks/AuctionTimeLeft"; @@ -46,7 +46,7 @@ export const QuickBid = ({ }: QuickBidProps): React.MemoExoticComponent<() => JSX.Element> => memo(() => { const tokens = useSelector((state: RootState) => - tokensSelector(state.wallet) + tokensSelector(state.wallet), ); const ownedToken = tokens.find((token) => token.id === loanTokenId); const currentBalance = new BigNumber(ownedToken?.amount ?? 0); @@ -55,7 +55,7 @@ export const QuickBid = ({ const [fee, setFee] = useState(new BigNumber(0.0001)); const { blocksRemaining } = useAuctionTime( vaultLiquidationHeight, - blockCount + blockCount, ); const isBalanceSufficient = currentBalance.gte(minNextBid); const { hasPendingJob, hasPendingBroadcastJob, constructSignedBidAndSend } = @@ -70,7 +70,7 @@ export const QuickBid = ({ }, []); const displayHigherBidWarning = new BigNumber(minNextBidInUSD).gte( - new BigNumber(totalCollateralsValueInUSD).times(1.2) + new BigNumber(totalCollateralsValueInUSD).times(1.2), ); const onQuickBid = async (): Promise => { await constructSignedBidAndSend({ @@ -92,7 +92,7 @@ export const QuickBid = ({ style={tailwind( "flex-1", { "-mt-0.5": Platform.OS === "ios" }, - { "-mt-1": Platform.OS === "android" } + { "-mt-1": Platform.OS === "android" }, )} > {/* -mt-1 above and mt-1 added below is kind of hack to solved React Navigation elevation bug on android for now. */} @@ -100,7 +100,7 @@ export const QuickBid = ({ style={tailwind( "flex-1", { "mt-1": Platform.OS === "ios" }, - { "mt-2": Platform.OS === "android" } + { "mt-2": Platform.OS === "android" }, )} > @@ -120,7 +120,7 @@ export const QuickBid = ({ light={tailwind("text-mono-light-v2-900")} dark={tailwind("text-mono-dark-v2-900")} style={tailwind( - "text-lg font-semibold-v2 flex-wrap ml-2" + "text-lg font-semibold-v2 flex-wrap ml-2", )} testID="quick_bid_min_next_bid_amount" > @@ -139,7 +139,7 @@ export const QuickBid = ({ light={tailwind("text-mono-light-v2-500")} dark={tailwind("text-mono-dark-v2-500")} style={tailwind( - "text-sm flex-wrap text-center font-normal-v2" + "text-sm flex-wrap text-center font-normal-v2", )} testID="quick_bid_min_next_bid_value" > @@ -159,7 +159,7 @@ export const QuickBid = ({ light={tailwind("text-mono-light-v2-500")} dark={tailwind("text-mono-dark-v2-500")} style={tailwind( - "text-sm flex-wrap text-center font-normal-v2" + "text-sm flex-wrap text-center font-normal-v2", )} testID="available_token_balance" > @@ -181,7 +181,7 @@ export const QuickBid = ({ lhs={{ value: translate( "components/QuickBid", - "Transaction fee" + "Transaction fee", ), testID: "transaction_fee_label", themedProps: { @@ -212,19 +212,19 @@ export const QuickBid = ({ renderText={(value: string) => ( {translate( "components/QuickBid", "Your bid is higher than the auction's collateral value of {{currency}}{{amount}}", - { amount: value, currency: "$" } + { amount: value, currency: "$" }, )} )} thousandSeparator value={getPrecisedTokenValue( - totalCollateralsValueInUSD + totalCollateralsValueInUSD, )} /> )} @@ -232,13 +232,13 @@ export const QuickBid = ({ ) : ( {translate( "components/QuickBid", "Insufficient {{symbol}} balance", - { symbol: loanTokenDisplaySymbol } + { symbol: loanTokenDisplaySymbol }, )} )} diff --git a/mobile-app/app/screens/AppNavigator/screens/Auctions/hooks/SignBidAndSend.tsx b/mobile-app/app/screens/AppNavigator/screens/Auctions/hooks/SignBidAndSend.tsx index 4e188fbf80..12f980e129 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Auctions/hooks/SignBidAndSend.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Auctions/hooks/SignBidAndSend.tsx @@ -13,7 +13,7 @@ import { firstTransactionSelector, hasOceanTXQueued, OceanTransaction, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { useAppDispatch } from "@hooks/useAppDispatch"; interface ConstructSignedBidAndSendProps { @@ -29,27 +29,27 @@ export const useSignBidAndSend = (): { hasPendingBroadcastJob: boolean; currentBroadcastJob: OceanTransaction; constructSignedBidAndSend: ( - props: ConstructSignedBidAndSendProps + props: ConstructSignedBidAndSendProps, ) => Promise; } => { const dispatch = useAppDispatch(); const logger = useLogger(); const hasPendingJob = useSelector((state: RootState) => - hasTxQueued(state.transactionQueue) + hasTxQueued(state.transactionQueue), ); const hasPendingBroadcastJob = useSelector((state: RootState) => - hasOceanTXQueued(state.ocean) + hasOceanTXQueued(state.ocean), ); const currentBroadcastJob = useSelector((state: RootState) => - firstTransactionSelector(state.ocean) + firstTransactionSelector(state.ocean), ); async function constructSignedBidAndSend( - props: ConstructSignedBidAndSendProps + props: ConstructSignedBidAndSendProps, ): Promise { try { const signer = async ( - account: WhaleWalletAccount + account: WhaleWalletAccount, ): Promise => { const builder = account.withTransactionBuilder(); const script = await account.getScript(); @@ -76,12 +76,12 @@ export const useSignBidAndSend = (): { { amount: props.tokenAmount.amount, token: props.displaySymbol, - } + }, ), drawerMessages: { preparing: translate( "screens/OceanInterface", - "Preparing to place bid…" + "Preparing to place bid…", ), waiting: translate( "components/QuickBid", @@ -89,7 +89,7 @@ export const useSignBidAndSend = (): { { amount: props.tokenAmount.amount, token: props.displaySymbol, - } + }, ), complete: translate( "components/QuickBid", @@ -97,11 +97,11 @@ export const useSignBidAndSend = (): { { amount: props.tokenAmount.amount, token: props.displaySymbol, - } + }, ), }, onBroadcast: props.onBroadcast, - }) + }), ); } catch (e) { logger.error(e); diff --git a/mobile-app/app/screens/AppNavigator/screens/Auctions/screens/AuctionDetailScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Auctions/screens/AuctionDetailScreen.tsx index 17752d8d2e..7ec0bc56ad 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Auctions/screens/AuctionDetailScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Auctions/screens/AuctionDetailScreen.tsx @@ -29,7 +29,7 @@ import { NumberRowV2 } from "@components/NumberRowV2"; import { PriceRateProps, PricesSection } from "@components/PricesSection"; import { useAppDispatch } from "@hooks/useAppDispatch"; import { useWalletContext } from "@shared-contexts/WalletContext"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { useThemeContext } from "@waveshq/walletkit-ui"; import { BidInfo } from "@screens/AppNavigator/screens/Auctions/components/BatchCard"; import { TokenIconGroupV2 } from "@components/TokenIconGroupV2"; @@ -49,7 +49,7 @@ type BatchDetailScreenProps = StackScreenProps< >; export function AuctionDetailScreen( - props: BatchDetailScreenProps + props: BatchDetailScreenProps, ): JSX.Element { const { batch: batchFromParam, vault } = props.route.params; const [batch, setBatch] = useState(batchFromParam); @@ -63,7 +63,7 @@ export function AuctionDetailScreen( const { auctions } = useSelector((state: RootState) => state.auctions); const blockCount = useSelector((state: RootState) => state.block.count) ?? 0; const bidHistory = useSelector( - (state: RootState) => state.auctions.bidHistory + (state: RootState) => state.auctions.bidHistory, ); const { minNextBidInToken, totalCollateralsValueInUSD, minNextBidInUSD } = @@ -92,7 +92,7 @@ export function AuctionDetailScreen( batchIndex: batch.index, client: client, size: 200, - }) + }), ); }); } @@ -100,14 +100,14 @@ export function AuctionDetailScreen( useEffect(() => { const _vault = auctions.find( - (auction) => auction.vaultId === vault.vaultId + (auction) => auction.vaultId === vault.vaultId, ); if (_vault === undefined) { return; } const _batch = _vault.batches.find( - (batch) => batch.index === batchFromParam.index + (batch) => batch.index === batchFromParam.index, ); if (_batch === undefined) { return; @@ -125,7 +125,7 @@ export function AuctionDetailScreen( }; const totalPrecisedCollateralsValue = getPrecisedTokenValue( - totalCollateralsValueInUSD + totalCollateralsValueInUSD, ); const precisedMinNextBidInUSD = getPrecisedTokenValue(minNextBidInUSD); @@ -134,7 +134,7 @@ export function AuctionDetailScreen( (collateral) => { const value = getTokenPrice( collateral.symbol, - new BigNumber(collateral.amount) + new BigNumber(collateral.amount), ); return { label: collateral.displaySymbol, @@ -143,7 +143,7 @@ export function AuctionDetailScreen( symbolUSDValue: value, usdTextStyle: tailwind("text-sm"), }; - } + }, ); const timeRemainingThemedProps = { @@ -186,7 +186,7 @@ export function AuctionDetailScreen( testID="auction_detail_collateral_group" size={36} symbols={batch.collaterals.map( - (collateral) => collateral.displaySymbol + (collateral) => collateral.displaySymbol, )} maxIconToDisplay={6} /> @@ -234,7 +234,7 @@ export function AuctionDetailScreen( lhs={{ value: translate( "components/AuctionDetailScreen", - "Total value" + "Total value", ), testID: "auction_detail_total_label", themedProps: { @@ -263,7 +263,7 @@ export function AuctionDetailScreen( progress={normalizedBlocks.toNumber()} color={getColor(timeRemainingThemedColor)} unfilledColor={getColor( - isLight ? "mono-light-v2-200" : "mono-dark-v2-200" + isLight ? "mono-light-v2-200" : "mono-dark-v2-200", )} borderWidth={0} width={null} @@ -271,7 +271,7 @@ export function AuctionDetailScreen( {translate("components/AuctionDetailScreen", "Auction closed")} diff --git a/mobile-app/app/screens/AppNavigator/screens/Auctions/screens/BidHistoryScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Auctions/screens/BidHistoryScreen.tsx index 6cb5a1ebb3..8964890a83 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Auctions/screens/BidHistoryScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Auctions/screens/BidHistoryScreen.tsx @@ -10,7 +10,7 @@ import { useSelector } from "react-redux"; import { useIsFocused } from "@react-navigation/native"; import { RootState } from "@store"; import { StackScreenProps } from "@react-navigation/stack"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { VaultAuctionBatchHistory } from "@defichain/whale-api-client/dist/api/loan"; import { auctions, fetchBidHistory } from "@store/auctions"; import { useAppDispatch } from "@hooks/useAppDispatch"; @@ -32,7 +32,7 @@ export function BidHistoryScreen(props: BatchDetailScreenProps): JSX.Element { const blockCount = useSelector((state: RootState) => state.block.count) ?? 0; const isFocused = useIsFocused(); const bidHistory = useSelector( - (state: RootState) => state.auctions.bidHistory + (state: RootState) => state.auctions.bidHistory, ); const { getTokenPrice } = useTokenPrice(); @@ -45,7 +45,7 @@ export function BidHistoryScreen(props: BatchDetailScreenProps): JSX.Element { batchIndex: batch.index, client: client, size: 200, - }) + }), ); } else { dispatch(auctions.actions.resetBidHistory()); @@ -94,7 +94,7 @@ export function BidHistoryScreen(props: BatchDetailScreenProps): JSX.Element { bidderAddress={item.address} bidAmountInUSD={getTokenPrice( batch.loan.symbol, - new BigNumber(item.amount) + new BigNumber(item.amount), )} bidBlockTime={item.block.time} /> diff --git a/mobile-app/app/screens/AppNavigator/screens/Auctions/screens/ConfirmPlaceBidScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Auctions/screens/ConfirmPlaceBidScreen.tsx index f999ca7211..ef7549d861 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Auctions/screens/ConfirmPlaceBidScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Auctions/screens/ConfirmPlaceBidScreen.tsx @@ -9,7 +9,7 @@ import { hasTxQueued, transactionQueue, hasOceanTXQueued, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { onTransactionBroadcast } from "@api/transaction/transaction_commands"; import { CTransactionSegWit, @@ -39,17 +39,17 @@ export function ConfirmPlaceBidScreen(props: Props): JSX.Element { const dispatch = useAppDispatch(); const logger = useLogger(); const hasPendingJob = useSelector((state: RootState) => - hasTxQueued(state.transactionQueue) + hasTxQueued(state.transactionQueue), ); const hasPendingBroadcastJob = useSelector((state: RootState) => - hasOceanTXQueued(state.ocean) + hasOceanTXQueued(state.ocean), ); const { bidAmount, estimatedFees, totalAuctionValue, vault, batch } = props.route.params; const blockCount = useSelector((state: RootState) => state.block.count) ?? 0; const { blocksRemaining } = useAuctionTime( vault.liquidationHeight, - blockCount + blockCount, ); const { address } = useWalletContext(); @@ -83,7 +83,7 @@ export function ConfirmPlaceBidScreen(props: Props): JSX.Element { () => { onTransactionBroadcast(isOnPage, navigation.dispatch); }, - logger + logger, ); setIsSubmitting(false); } @@ -132,7 +132,7 @@ export function ConfirmPlaceBidScreen(props: Props): JSX.Element { {translate("screens/PlaceBidScreen", "Auction timeout")} @@ -193,7 +193,7 @@ export function ConfirmPlaceBidScreen(props: Props): JSX.Element { > {translate( "screens/ConfirmPlaceBidScreen", - "Amount will be deducted from your current wallet" + "Amount will be deducted from your current wallet", )} , onBroadcast: () => void, - logger: NativeLoggingProps + logger: NativeLoggingProps, ): Promise { try { const signer = async ( - account: WhaleWalletAccount + account: WhaleWalletAccount, ): Promise => { const builder = account.withTransactionBuilder(); const script = await account.getScript(); @@ -248,27 +248,27 @@ async function constructSignedBidAndSend( title: translate( "screens/ConfirmPlaceBidScreen", "Placing {{amount}} {{token}} bid", - { amount: tokenAmount.amount, token: displaySymbol } + { amount: tokenAmount.amount, token: displaySymbol }, ), drawerMessages: { preparing: translate( "screens/ConfirmPlaceBidScreen", "Preparing placing {{amount}} {{token}} bid", - { amount: tokenAmount.amount, token: displaySymbol } + { amount: tokenAmount.amount, token: displaySymbol }, ), waiting: translate( "screens/ConfirmPlaceBidScreen", "Placing {{amount}} {{token}} bid", - { amount: tokenAmount.amount, token: displaySymbol } + { amount: tokenAmount.amount, token: displaySymbol }, ), complete: translate( "screens/ConfirmPlaceBidScreen", "Placed {{amount}} {{token}} bid", - { amount: tokenAmount.amount, token: displaySymbol } + { amount: tokenAmount.amount, token: displaySymbol }, ), }, onBroadcast, - }) + }), ); } catch (e) { logger.error(e); diff --git a/mobile-app/app/screens/AppNavigator/screens/Auctions/screens/PlaceBidScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Auctions/screens/PlaceBidScreen.tsx index e25e34bb01..b58b4c04ff 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Auctions/screens/PlaceBidScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Auctions/screens/PlaceBidScreen.tsx @@ -11,7 +11,7 @@ import { hasTxQueued, hasOceanTXQueued, tokensSelector, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { translate } from "@translations"; import { useBottomSheet } from "@hooks/useBottomSheet"; import { NumericFormat as NumberFormat } from "react-number-format"; @@ -26,7 +26,7 @@ import { BottomSheetWithNav, } from "@components/BottomSheetWithNav"; import { useLogger } from "@shared-contexts/NativeLoggingProvider"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { useTokenPrice } from "@screens/AppNavigator/screens/Portfolio/hooks/TokenPrice"; import { TokenDropdownButton, diff --git a/mobile-app/app/screens/AppNavigator/screens/Dex/CompositeSwap/CompositeSwapScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Dex/CompositeSwap/CompositeSwapScreen.tsx index c13502cf8a..99ecef1dcf 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Dex/CompositeSwap/CompositeSwapScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Dex/CompositeSwap/CompositeSwapScreen.tsx @@ -17,7 +17,7 @@ import { DFITokenSelector, DFIUtxoSelector, tokensSelector, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { queueConvertTransaction, useConversion, @@ -26,7 +26,7 @@ import { useLogger } from "@shared-contexts/NativeLoggingProvider"; import { useWhaleApiClient, useWhaleRpcClient, -} from "@waveshq/walletkit-ui/dist/contexts"; +} from "@waveshq/walletkit-ui/contexts"; import { PoolPairData } from "@defichain/whale-api-client/dist/api/poolpairs"; import { StackScreenProps } from "@react-navigation/stack"; import { @@ -1113,8 +1113,8 @@ export function CompositeSwapScreen({ route }: Props): JSX.Element { route.params.tokenSelectOption?.to?.isDisabled ? TokenDropdownButtonStatus.Locked : selectedTokenA === undefined || toTokens.length === 0 - ? TokenDropdownButtonStatus.Disabled - : TokenDropdownButtonStatus.Enabled + ? TokenDropdownButtonStatus.Disabled + : TokenDropdownButtonStatus.Enabled } /> diff --git a/mobile-app/app/screens/AppNavigator/screens/Dex/CompositeSwap/ConfirmCompositeSwapScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Dex/CompositeSwap/ConfirmCompositeSwapScreen.tsx index b970724068..cd59729a3f 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Dex/CompositeSwap/ConfirmCompositeSwapScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Dex/CompositeSwap/ConfirmCompositeSwapScreen.tsx @@ -10,7 +10,7 @@ import { hasTxQueued, hasOceanTXQueued, transactionQueue, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { translate } from "@translations"; import { CompositeSwap, @@ -78,10 +78,10 @@ export function ConfirmCompositeSwapScreen({ route }: Props): JSX.Element { const logger = useLogger(); const { getTokenPrice } = useTokenPrice(); const hasPendingJob = useSelector((state: RootState) => - hasTxQueued(state.transactionQueue) + hasTxQueued(state.transactionQueue), ); const hasPendingBroadcastJob = useSelector((state: RootState) => - hasOceanTXQueued(state.ocean) + hasOceanTXQueued(state.ocean), ); const blockCount = useSelector((state: RootState) => state.block.count ?? 0); @@ -133,7 +133,7 @@ export function ConfirmCompositeSwapScreen({ route }: Props): JSX.Element { () => { onTransactionBroadcast(isOnPage, navigation.dispatch); }, - logger + logger, ); } else { await constructSignedSwapAndSend( @@ -144,7 +144,7 @@ export function ConfirmCompositeSwapScreen({ route }: Props): JSX.Element { () => { onTransactionBroadcast(isOnPage, navigation.dispatch); }, - logger + logger, ); } setIsSubmitting(false); @@ -156,7 +156,7 @@ export function ConfirmCompositeSwapScreen({ route }: Props): JSX.Element { title: translate("screens/Settings", "Cancel transaction"), message: translate( "screens/Settings", - "By cancelling, you will lose any changes you made for your transaction." + "By cancelling, you will lose any changes you made for your transaction.", ), buttons: [ { @@ -170,7 +170,7 @@ export function ConfirmCompositeSwapScreen({ route }: Props): JSX.Element { navigation.navigate( originScreen === ScreenName.DEX_screen ? ScreenName.DEX_screen - : ScreenName.PORTFOLIO_screen + : ScreenName.PORTFOLIO_screen, ); }, }, @@ -185,7 +185,7 @@ export function ConfirmCompositeSwapScreen({ route }: Props): JSX.Element { {conversion?.isConversionRequired && @@ -268,7 +268,7 @@ export function ConfirmCompositeSwapScreen({ route }: Props): JSX.Element { lhs={{ value: translate( "screens/ConfirmCompositeSwapScreen", - "Slippage tolerance" + "Slippage tolerance", ), testID: "confirm_slippage_fee_label", themedProps: { @@ -295,7 +295,7 @@ export function ConfirmCompositeSwapScreen({ route }: Props): JSX.Element { lhs={{ value: translate( "screens/ConfirmCompositeSwapScreen", - "Total fees" + "Total fees", ), testID: "transaction_fee", themedProps: { @@ -328,7 +328,7 @@ export function ConfirmCompositeSwapScreen({ route }: Props): JSX.Element { lhs={{ value: translate( "screens/ConfirmCompositeSwapScreen", - "Transaction fee" + "Transaction fee", ), testID: "transaction_fee", themedProps: { @@ -348,7 +348,7 @@ export function ConfirmCompositeSwapScreen({ route }: Props): JSX.Element { lhs={{ value: translate( "screens/ConfirmCompositeSwapScreen", - "Settlement block" + "Settlement block", ), testID: "settlement_block", themedProps: { @@ -381,7 +381,7 @@ export function ConfirmCompositeSwapScreen({ route }: Props): JSX.Element { lhs={{ value: translate( "screens/ConfirmCompositeSwapScreen", - "Estimated to receive" + "Estimated to receive", ), testID: "confirm_text_receive", themedProps: { @@ -409,7 +409,7 @@ export function ConfirmCompositeSwapScreen({ route }: Props): JSX.Element { "Settlement value {{percentageChange}}", { percentageChange: futureSwap.oraclePriceText, - } + }, ), testID: "confirm_settlement_value", }} @@ -426,7 +426,7 @@ export function ConfirmCompositeSwapScreen({ route }: Props): JSX.Element { lhs={{ value: translate( "screens/ConfirmCompositeSwapScreen", - "Estimated to receive (incl. all fees)" + "Estimated to receive (incl. all fees)", ), testID: "estimated_to_receive", themedProps: { @@ -441,7 +441,7 @@ export function ConfirmCompositeSwapScreen({ route }: Props): JSX.Element { usdAmount: getTokenPrice( tokenB.symbol, new BigNumber(estimatedLessFeesAfterSlippage), - false + false, ), themedProps: { style: tailwind("font-semibold-v2 text-right"), @@ -519,7 +519,7 @@ async function constructSignedSwapAndSend( slippage: BigNumber, dispatch: Dispatch, onBroadcast: () => void, - logger: NativeLoggingProps + logger: NativeLoggingProps, ): Promise { try { const maxPrice = cSwapForm.amountFrom @@ -527,7 +527,7 @@ async function constructSignedSwapAndSend( .times(slippage.plus(1)) .decimalPlaces(8); const signer = async ( - account: WhaleWalletAccount + account: WhaleWalletAccount, ): Promise => { const builder = account.withTransactionBuilder(); const script = await account.getScript(); @@ -538,10 +538,10 @@ async function constructSignedSwapAndSend( fromTokenId: Number( cSwapForm.tokenFrom.id === "0_unified" ? "0" - : cSwapForm.tokenFrom.id + : cSwapForm.tokenFrom.id, ), toTokenId: Number( - cSwapForm.tokenTo.id === "0_unified" ? "0" : cSwapForm.tokenTo.id + cSwapForm.tokenTo.id === "0_unified" ? "0" : cSwapForm.tokenTo.id, ), fromAmount: cSwapForm.amountFrom, maxPrice, @@ -564,7 +564,7 @@ async function constructSignedSwapAndSend( amountB: cSwapForm.amountTo.toFixed(8), symbolA: cSwapForm.tokenFrom.displaySymbol, symbolB: cSwapForm.tokenTo.displaySymbol, - } + }, ), drawerMessages: { waiting: translate( @@ -575,7 +575,7 @@ async function constructSignedSwapAndSend( amountB: cSwapForm.amountTo.toFixed(8), symbolA: cSwapForm.tokenFrom.displaySymbol, symbolB: cSwapForm.tokenTo.displaySymbol, - } + }, ), complete: translate( "screens/OceanInterface", @@ -585,11 +585,11 @@ async function constructSignedSwapAndSend( amountB: cSwapForm.amountTo.toFixed(8), symbolA: cSwapForm.tokenFrom.displaySymbol, symbolB: cSwapForm.tokenTo.displaySymbol, - } + }, ), }, onBroadcast, - }) + }), ); } catch (e) { logger.error(e); @@ -611,11 +611,11 @@ async function constructSignedFutureSwapAndSend( futureSwap: FutureSwapForm, dispatch: Dispatch, onBroadcast: () => void, - logger: NativeLoggingProps + logger: NativeLoggingProps, ): Promise { try { const signer = async ( - account: WhaleWalletAccount + account: WhaleWalletAccount, ): Promise => { const builder = account.withTransactionBuilder(); const script = await account.getScript(); @@ -644,24 +644,24 @@ async function constructSignedFutureSwapAndSend( fromTokenDisplaySymbol: futureSwap.fromTokenDisplaySymbol, toTokenDisplaySymbol: futureSwap.toTokenDisplaySymbol, settlementBlock: futureSwap.executionBlock, - } + }, ), drawerMessages: { preparing: translate( "screens/OceanInterface", - "Preparing your transaction…" + "Preparing your transaction…", ), waiting: translate( "screens/OceanInterface", - "Processing future swap…" + "Processing future swap…", ), complete: translate( "screens/OceanInterface", - "Future Swap confirmed for next settlement block" + "Future Swap confirmed for next settlement block", ), }, onBroadcast, - }) + }), ); } catch (e) { logger.error(e); diff --git a/mobile-app/app/screens/AppNavigator/screens/Dex/DexAddLiquidity.tsx b/mobile-app/app/screens/AppNavigator/screens/Dex/DexAddLiquidity.tsx index 648f02ab14..f92cd6852f 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Dex/DexAddLiquidity.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Dex/DexAddLiquidity.tsx @@ -19,7 +19,7 @@ import { WalletToken, hasTxQueued, hasOceanTXQueued, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { useSelector } from "react-redux"; import { RootState } from "@store"; import { @@ -403,15 +403,15 @@ export function AddLiquidityScreen(props: Props): JSX.Element { hasAError ? TransactionCardStatus.Error : isInputAFocus - ? TransactionCardStatus.Active - : undefined, + ? TransactionCardStatus.Active + : undefined, ); setTokenBTransactionCardStatus( hasBError ? TransactionCardStatus.Error : isInputBFocus - ? TransactionCardStatus.Active - : undefined, + ? TransactionCardStatus.Active + : undefined, ); }, [hasAError, hasBError, isInputAFocus, isInputBFocus]); diff --git a/mobile-app/app/screens/AppNavigator/screens/Dex/DexConfirmAddLiquidity.tsx b/mobile-app/app/screens/AppNavigator/screens/Dex/DexConfirmAddLiquidity.tsx index 01e40a9e04..ef798e9046 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Dex/DexConfirmAddLiquidity.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Dex/DexConfirmAddLiquidity.tsx @@ -20,7 +20,7 @@ import { hasTxQueued, hasOceanTXQueued, transactionQueue, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { tailwind } from "@tailwind"; import { translate } from "@translations"; import { onTransactionBroadcast } from "@api/transaction/transaction_commands"; @@ -42,10 +42,10 @@ type Props = StackScreenProps; export function ConfirmAddLiquidityScreen({ route }: Props): JSX.Element { const hasPendingJob = useSelector((state: RootState) => - hasTxQueued(state.transactionQueue) + hasTxQueued(state.transactionQueue), ); const hasPendingBroadcastJob = useSelector((state: RootState) => - hasOceanTXQueued(state.ocean) + hasOceanTXQueued(state.ocean), ); const { pair, @@ -89,7 +89,7 @@ export function ConfirmAddLiquidityScreen({ route }: Props): JSX.Element { () => { onTransactionBroadcast(isOnPage, navigation.dispatch); }, - logger + logger, ); setIsSubmitting(false); } @@ -100,7 +100,7 @@ export function ConfirmAddLiquidityScreen({ route }: Props): JSX.Element { title: translate("screens/Settings", "Cancel transaction"), message: translate( "screens/Settings", - "By cancelling, you will lose any changes you made for your transaction." + "By cancelling, you will lose any changes you made for your transaction.", ), buttons: [ { @@ -114,7 +114,7 @@ export function ConfirmAddLiquidityScreen({ route }: Props): JSX.Element { navigation.navigate( originScreen === ScreenName.DEX_screen ? ScreenName.DEX_screen - : ScreenName.PORTFOLIO_screen + : ScreenName.PORTFOLIO_screen, ); }, }, @@ -134,7 +134,7 @@ export function ConfirmAddLiquidityScreen({ route }: Props): JSX.Element { testID="text_add_amount" title={translate( "screens/ConfirmAddLiq", - "You will receive LP tokens" + "You will receive LP tokens", )} fromAddressLabel={addressLabel} /> @@ -162,7 +162,7 @@ export function ConfirmAddLiquidityScreen({ route }: Props): JSX.Element { /> {conversion?.isConversionRequired && @@ -288,9 +288,9 @@ export function ConfirmAddLiquidityScreen({ route }: Props): JSX.Element { testID: "lp_tokens_to_receive_value", usdAmount: getTokenPrice( pair.tokenA.symbol, - new BigNumber(tokenAAmount) + new BigNumber(tokenAAmount), ).plus( - getTokenPrice(pair.tokenB.symbol, new BigNumber(tokenBAmount)) + getTokenPrice(pair.tokenB.symbol, new BigNumber(tokenBAmount)), ), themedProps: { style: tailwind("font-semibold-v2 text-sm"), @@ -326,11 +326,11 @@ async function constructSignedAddLiqAndSend( }, dispatch: Dispatch, onBroadcast: () => void, - logger: NativeLoggingProps + logger: NativeLoggingProps, ): Promise { try { const signer = async ( - account: WhaleWalletAccount + account: WhaleWalletAccount, ): Promise => { const builder = account.withTransactionBuilder(); const script = await account.getScript(); @@ -368,12 +368,12 @@ async function constructSignedAddLiqAndSend( totalToken: addLiqForm.lmTotalTokens, symbolA: addLiqForm.tokenASymbol, symbolB: addLiqForm.tokenBSymbol, - } + }, ), drawerMessages: { preparing: translate( "screens/OceanInterface", - "Preparing to add liquidity…" + "Preparing to add liquidity…", ), waiting: translate( "screens/OceanInterface", @@ -382,7 +382,7 @@ async function constructSignedAddLiqAndSend( totalToken: addLiqForm.lmTotalTokens, symbolA: addLiqForm.tokenASymbol, symbolB: addLiqForm.tokenBSymbol, - } + }, ), complete: translate( "screens/OceanInterface", @@ -391,11 +391,11 @@ async function constructSignedAddLiqAndSend( totalToken: addLiqForm.lmTotalTokens, symbolA: addLiqForm.tokenASymbol, symbolB: addLiqForm.tokenBSymbol, - } + }, ), }, onBroadcast, - }) + }), ); } catch (e) { logger.error(e); diff --git a/mobile-app/app/screens/AppNavigator/screens/Dex/DexConfirmRemoveLiquidity.tsx b/mobile-app/app/screens/AppNavigator/screens/Dex/DexConfirmRemoveLiquidity.tsx index 54b6314743..24af0d7ecd 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Dex/DexConfirmRemoveLiquidity.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Dex/DexConfirmRemoveLiquidity.tsx @@ -16,7 +16,7 @@ import { hasTxQueued, hasOceanTXQueued, transactionQueue, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { tailwind } from "@tailwind"; import { translate } from "@translations"; import { ScreenName } from "@screens/enum"; @@ -45,10 +45,10 @@ export function RemoveLiquidityConfirmScreen({ route }: Props): JSX.Element { const dispatch = useAppDispatch(); const { getTokenPrice } = useTokenPrice(); const hasPendingJob = useSelector((state: RootState) => - hasTxQueued(state.transactionQueue) + hasTxQueued(state.transactionQueue), ); const hasPendingBroadcastJob = useSelector((state: RootState) => - hasOceanTXQueued(state.ocean) + hasOceanTXQueued(state.ocean), ); const [isSubmitting, setIsSubmitting] = useState(false); const navigation = useNavigation>(); @@ -59,7 +59,7 @@ export function RemoveLiquidityConfirmScreen({ route }: Props): JSX.Element { const sharesUsdAmount = getTokenPrice( pair.symbol, new BigNumber(amount), - true + true, ); useEffect(() => { setIsOnPage(true); @@ -85,7 +85,7 @@ export function RemoveLiquidityConfirmScreen({ route }: Props): JSX.Element { title: translate("screens/Settings", "Cancel transaction"), message: translate( "screens/Settings", - "By cancelling, you will lose any changes you made for your transaction." + "By cancelling, you will lose any changes you made for your transaction.", ), buttons: [ { @@ -99,7 +99,7 @@ export function RemoveLiquidityConfirmScreen({ route }: Props): JSX.Element { navigation.navigate( originScreen === ScreenName.DEX_screen ? ScreenName.DEX_screen - : ScreenName.PORTFOLIO_screen + : ScreenName.PORTFOLIO_screen, ); }, }, @@ -121,7 +121,7 @@ export function RemoveLiquidityConfirmScreen({ route }: Props): JSX.Element { testID="text_remove_liquidity_amount" title={translate( "screens/ConfirmRemoveLiquidity", - "You are removing LP tokens" + "You are removing LP tokens", )} /> @@ -136,7 +136,7 @@ export function RemoveLiquidityConfirmScreen({ route }: Props): JSX.Element { lhs={{ value: translate( "screens/ConfirmRemoveLiquidity", - "Transaction fee" + "Transaction fee", ), themedProps: { light: tailwind("text-mono-light-v2-500"), @@ -185,12 +185,12 @@ export function RemoveLiquidityConfirmScreen({ route }: Props): JSX.Element { "{{token}} to receive", { token: pair.tokenA.displaySymbol, - } + }, ), value: BigNumber.max(tokenAAmount, 0).toFixed(8), symbolUSDValue: getTokenPrice( pair.tokenA.symbol, - new BigNumber(tokenAAmount) + new BigNumber(tokenAAmount), ), usdTextStyle: tailwind("text-sm"), }, @@ -200,12 +200,12 @@ export function RemoveLiquidityConfirmScreen({ route }: Props): JSX.Element { "{{token}} to receive", { token: pair.tokenB.displaySymbol, - } + }, ), value: BigNumber.max(tokenBAmount, 0).toFixed(8), symbolUSDValue: getTokenPrice( pair.tokenB.symbol, - new BigNumber(tokenBAmount) + new BigNumber(tokenBAmount), ), usdTextStyle: tailwind("text-sm"), }, @@ -215,7 +215,7 @@ export function RemoveLiquidityConfirmScreen({ route }: Props): JSX.Element { lhs={{ value: translate( "screens/ConfirmRemoveLiquidity", - "LP tokens to remove" + "LP tokens to remove", ), themedProps: { light: tailwind("text-mono-light-v2-500"), @@ -242,7 +242,7 @@ export function RemoveLiquidityConfirmScreen({ route }: Props): JSX.Element { isDisabled={isSubmitting || hasPendingJob || hasPendingBroadcastJob} label={translate( "screens/ConfirmRemoveLiquidity", - "Remove liquidity" + "Remove liquidity", )} onSubmit={onSubmit} onCancel={onCancel} @@ -258,7 +258,7 @@ async function constructSignedRemoveLiqAndSend( pair: PoolPairData, amount: BigNumber, dispatch: Dispatch, - onBroadcast: () => void + onBroadcast: () => void, ): Promise { const tokenId = Number(pair.id); const symbol = @@ -267,7 +267,7 @@ async function constructSignedRemoveLiqAndSend( : pair.symbol; const signer = async ( - account: WhaleWalletAccount + account: WhaleWalletAccount, ): Promise => { const builder = account.withTransactionBuilder(); const script = await account.getScript(); @@ -290,12 +290,12 @@ async function constructSignedRemoveLiqAndSend( { symbol: symbol, amount: amount.toFixed(8), - } + }, ), drawerMessages: { preparing: translate( "screens/OceanInterface", - "Preparing to remove liquidity…" + "Preparing to remove liquidity…", ), waiting: translate( "screens/OceanInterface", @@ -303,7 +303,7 @@ async function constructSignedRemoveLiqAndSend( { symbol: symbol, amount: amount.toFixed(8), - } + }, ), complete: translate( "screens/OceanInterface", @@ -311,10 +311,10 @@ async function constructSignedRemoveLiqAndSend( { symbol: symbol, amount: amount.toFixed(8), - } + }, ), }, onBroadcast, - }) + }), ); } diff --git a/mobile-app/app/screens/AppNavigator/screens/Dex/DexNavigator.tsx b/mobile-app/app/screens/AppNavigator/screens/Dex/DexNavigator.tsx index 30096013d3..37999486de 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Dex/DexNavigator.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Dex/DexNavigator.tsx @@ -4,7 +4,7 @@ import { createStackNavigator } from "@react-navigation/stack"; import BigNumber from "bignumber.js"; import { HeaderFont } from "@components/Text"; import { translate } from "@translations"; -import { WalletToken } from "@waveshq/walletkit-ui/dist/store"; +import { WalletToken } from "@waveshq/walletkit-ui/store"; import { useNavigatorScreenOptions } from "@hooks/useNavigatorScreenOptions"; import { HeaderNetworkStatus } from "@components/HeaderNetworkStatus"; import { tailwind } from "@tailwind"; diff --git a/mobile-app/app/screens/AppNavigator/screens/Dex/DexRemoveLiquidity.tsx b/mobile-app/app/screens/AppNavigator/screens/Dex/DexRemoveLiquidity.tsx index 1ead04a8ba..adf07348f6 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Dex/DexRemoveLiquidity.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Dex/DexRemoveLiquidity.tsx @@ -11,13 +11,13 @@ import { ThemedTouchableOpacityV2, ThemedViewV2, } from "@components/themed"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { RootState } from "@store"; import { hasTxQueued, hasOceanTXQueued, tokenSelector, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { tailwind } from "@tailwind"; import { translate } from "@translations"; import { useLogger } from "@shared-contexts/NativeLoggingProvider"; @@ -51,10 +51,10 @@ export function RemoveLiquidityScreen(props: Props): JSX.Element { const toast = useToast(); const [fee, setFee] = useState(new BigNumber(0.0001)); const hasPendingJob = useSelector((state: RootState) => - hasTxQueued(state.transactionQueue) + hasTxQueued(state.transactionQueue), ); const hasPendingBroadcastJob = useSelector((state: RootState) => - hasOceanTXQueued(state.ocean) + hasOceanTXQueued(state.ocean), ); const { getTokenPrice } = useTokenPrice(); // this component state @@ -79,10 +79,10 @@ export function RemoveLiquidityScreen(props: Props): JSX.Element { // gather required data const { pair, pairInfo, originScreen } = props.route.params; const tokenA = useSelector((state: RootState) => - tokenSelector(state.wallet, pair.tokenA.id) + tokenSelector(state.wallet, pair.tokenA.id), ); const tokenB = useSelector((state: RootState) => - tokenSelector(state.wallet, pair.tokenB.id) + tokenSelector(state.wallet, pair.tokenB.id), ); useEffect(() => { @@ -90,8 +90,8 @@ export function RemoveLiquidityScreen(props: Props): JSX.Element { hasError ? TransactionCardStatus.Error : isInputFocus - ? TransactionCardStatus.Active - : TransactionCardStatus.Default + ? TransactionCardStatus.Active + : TransactionCardStatus.Default, ); }, [hasError, isInputFocus]); @@ -123,10 +123,10 @@ export function RemoveLiquidityScreen(props: Props): JSX.Element { setValidity( new BigNumber(tokenToRemove).isGreaterThan(new BigNumber(0)) && new BigNumber(tokenToRemove).isLessThanOrEqualTo( - new BigNumber(pairInfo.amount) + new BigNumber(pairInfo.amount), ) && !hasPendingJob && - !hasPendingBroadcastJob + !hasPendingBroadcastJob, ); }, [tokenToRemove]); @@ -151,7 +151,7 @@ export function RemoveLiquidityScreen(props: Props): JSX.Element { type: "wallet_toast", placement: "top", duration: TOAST_DURATION, - } + }, ); } @@ -224,7 +224,7 @@ export function RemoveLiquidityScreen(props: Props): JSX.Element { setTokenBAmount(tokenB); setTokenToRemove(amountString); }, - [pair] + [pair], ); useEffect(() => { @@ -244,7 +244,7 @@ export function RemoveLiquidityScreen(props: Props): JSX.Element { const sharesUsdAmount = getTokenPrice( pair.symbol, new BigNumber(amount), - true + true, ); return ( @@ -260,7 +260,7 @@ export function RemoveLiquidityScreen(props: Props): JSX.Element { tokenBSymbol={pair.tokenB.displaySymbol} headerLabel={translate( "screens/RemoveLiquidity", - "View pool share" + "View pool share", )} onPress={expandModal} testID="view_pool_button" @@ -294,12 +294,12 @@ export function RemoveLiquidityScreen(props: Props): JSX.Element { "{{token}} to receive", { token: pair.tokenA.displaySymbol, - } + }, ), value: BigNumber.max(tokenAAmount, 0).toFixed(8), symbolUSDValue: getTokenPrice( pair.tokenA.symbol, - tokenAAmount + tokenAAmount, ), usdTextStyle: tailwind("text-sm"), }, @@ -309,12 +309,12 @@ export function RemoveLiquidityScreen(props: Props): JSX.Element { "{{token}} to receive", { token: pair.tokenB.displaySymbol, - } + }, ), value: BigNumber.max(tokenBAmount, 0).toFixed(8), symbolUSDValue: getTokenPrice( pair.tokenB.symbol, - tokenBAmount + tokenBAmount, ), usdTextStyle: tailwind("text-sm"), }, @@ -322,7 +322,7 @@ export function RemoveLiquidityScreen(props: Props): JSX.Element { resultingLplhs={{ value: translate( "screens/RemoveLiquidity", - "LP tokens to remove" + "LP tokens to remove", ), themedProps: { light: tailwind("text-mono-light-v2-500"), @@ -351,7 +351,7 @@ export function RemoveLiquidityScreen(props: Props): JSX.Element { > {translate( "screens/ConvertScreen", - "Review full details in the next screen" + "Review full details in the next screen", )} diff --git a/mobile-app/app/screens/AppNavigator/screens/Dex/DexScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Dex/DexScreen.tsx index 51193ec53f..91cc943c22 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Dex/DexScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Dex/DexScreen.tsx @@ -18,7 +18,7 @@ import { } from "@components/themed"; import { tailwind } from "@tailwind"; import { translate } from "@translations"; -import { tokensSelector, WalletToken } from "@waveshq/walletkit-ui/dist/store"; +import { tokensSelector, WalletToken } from "@waveshq/walletkit-ui/store"; import { RootState } from "@store"; import { debounce } from "lodash"; import { HeaderSearchInput } from "@components/HeaderSearchInput"; @@ -48,7 +48,7 @@ export function DexScreen(): JSX.Element { const navigation = useNavigation>(); const [activeTab, setActiveTab] = useState(TabKey.AvailablePoolPair); const tokens = useSelector((state: RootState) => - tokensSelector(state.wallet) + tokensSelector(state.wallet), ); const onButtonGroupChange = (buttonGroupTabKey: ButtonGroupTabKey): void => { @@ -57,7 +57,7 @@ export function DexScreen(): JSX.Element { }; const { poolpairs: pairs, hasFetchedPoolpairData } = useSelector( - (state: RootState) => state.wallet + (state: RootState) => state.wallet, ); const yourLPTokens = useSelector(() => { const _yourLPTokens: Array> = tokens @@ -156,7 +156,7 @@ export function DexScreen(): JSX.Element { .filter((pair) => pair.data.displaySymbol .toLowerCase() - .includes(searchString.trim().toLowerCase()) + .includes(searchString.trim().toLowerCase()), ) .sort( (firstPair, secondPair) => @@ -165,14 +165,14 @@ export function DexScreen(): JSX.Element { .toNumber() ?? new BigNumber(secondPair.data.id) .minus(firstPair.data.id) - .toNumber() - ) + .toNumber(), + ), ); } else { setFilteredAvailablePairs([]); } }, 500), - [activeTab, pairs] + [activeTab, pairs], ); useEffect(() => { @@ -211,7 +211,7 @@ export function DexScreen(): JSX.Element { }, [showSearchInput, searchString]); const [activeButtonGroup, setActiveButtonGroup] = useState( - ButtonGroupTabKey.AllPairs + ButtonGroupTabKey.AllPairs, ); const { isFavouritePoolpair, favouritePoolpairs } = useFavouritePoolpairContext(); @@ -250,11 +250,11 @@ export function DexScreen(): JSX.Element { .toNumber() ?? new BigNumber(secondPair.data.id) .minus(firstPair.data.id) - .toNumber() + .toNumber(), ); setFilteredAvailablePairs(filteredPairs); }, - [pairs, favouritePoolpairs] + [pairs, favouritePoolpairs], ); useEffect(() => { @@ -293,7 +293,7 @@ export function DexScreen(): JSX.Element { new BigNumber(secondPair.data.totalLiquidity.usd ?? 0) .minus(firstPair.data.totalLiquidity.usd ?? 0) .toNumber() ?? - new BigNumber(secondPair.data.id).minus(firstPair.data.id).toNumber() + new BigNumber(secondPair.data.id).minus(firstPair.data.id).toNumber(), ) .slice(0, 5); setTopLiquidityPairs(sorted); @@ -322,11 +322,11 @@ export function DexScreen(): JSX.Element { ? translate( "screens/DexScreen", "Search results for “{{input}}”", - { input: searchString?.trim() } + { input: searchString?.trim() }, ) : translate( "screens/DexScreen", - "Search for pool pair with token name" + "Search for pool pair with token name", )} @@ -336,7 +336,7 @@ export function DexScreen(): JSX.Element { light={tailwind("bg-mono-light-v2-00 border-mono-light-v2-100")} dark={tailwind("bg-mono-dark-v2-00 border-mono-dark-v2-100")} style={tailwind( - "flex flex-col items-center pt-4 rounded-b-2xl border-b" + "flex flex-col items-center pt-4 rounded-b-2xl border-b", )} > @@ -447,7 +447,7 @@ const DexFilterPillGroup = React.memo( horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={tailwind( - "flex justify-between items-center flex-row px-5" + "flex justify-between items-center flex-row px-5", )} > ); - } + }, ); diff --git a/mobile-app/app/screens/AppNavigator/screens/Dex/PoolPairDetailsScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Dex/PoolPairDetailsScreen.tsx index 238caa8ccd..9bd8273196 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Dex/PoolPairDetailsScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Dex/PoolPairDetailsScreen.tsx @@ -17,7 +17,7 @@ import { poolPairSelector, tokensSelector, WalletToken, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { tailwind } from "@tailwind"; import { translate } from "@translations"; import BigNumber from "bignumber.js"; @@ -45,10 +45,10 @@ type Props = StackScreenProps; export function PoolPairDetailsScreen({ route }: Props): JSX.Element { const { id } = route.params; const poolPair = useSelector((state: RootState) => - poolPairSelector(state.wallet, id) + poolPairSelector(state.wallet, id), ); const tokens = useSelector((state: RootState) => - tokensSelector(state.wallet) + tokensSelector(state.wallet), ); const { getTokenUrl } = useDeFiScanContext(); const navigation = useNavigation>(); @@ -72,7 +72,7 @@ export function PoolPairDetailsScreen({ route }: Props): JSX.Element { headerTitle: translate( "screens/PoolPairDetailsScreen", "{{poolPair}} Pool", - { poolPair: poolPair.data.displaySymbol } + { poolPair: poolPair.data.displaySymbol }, ), }); }, [navigation]); @@ -245,7 +245,7 @@ function Header(props: { isFavouritePair={props.isFavouritePair} onPress={() => { showToast( - props.isFavouritePair ? "UNSET_FAVOURITE" : "SET_FAVOURITE" + props.isFavouritePair ? "UNSET_FAVOURITE" : "SET_FAVOURITE", ); props.setFavouritePair(props.poolPairId); }} @@ -291,8 +291,8 @@ function PoolPairDetail({ poolPair }: { poolPair: DexItem }): JSX.Element { getTokenPrice( poolPair.data.symbol, new BigNumber(poolPair.data.totalLiquidity.token), - true - ) + true, + ), ), usdTextStyle: tailwind("text-sm"), usdContainerStyle: tailwind("pt-1"), @@ -304,7 +304,7 @@ function PoolPairDetail({ poolPair }: { poolPair: DexItem }): JSX.Element { value: translate( "screens/PoolPairDetailsScreen", "Pooled {{symbol}}", - { symbol: poolPair.data.tokenA.displaySymbol } + { symbol: poolPair.data.tokenA.displaySymbol }, ), testID: "pooled_tokenA", }} @@ -313,7 +313,7 @@ function PoolPairDetail({ poolPair }: { poolPair: DexItem }): JSX.Element { suffix: ` ${poolPair.data.tokenA.displaySymbol}`, usdAmount: getTokenPrice( poolPair.data.tokenA.symbol, - new BigNumber(poolPair.data.tokenA.reserve) + new BigNumber(poolPair.data.tokenA.reserve), ), usdTextStyle: tailwind("text-sm"), usdContainerStyle: tailwind("pt-1"), @@ -325,7 +325,7 @@ function PoolPairDetail({ poolPair }: { poolPair: DexItem }): JSX.Element { value: translate( "screens/PoolPairDetailsScreen", "Pooled {{symbol}}", - { symbol: poolPair.data.tokenB.displaySymbol } + { symbol: poolPair.data.tokenB.displaySymbol }, ), testID: "pooled_tokenB", }} @@ -334,7 +334,7 @@ function PoolPairDetail({ poolPair }: { poolPair: DexItem }): JSX.Element { suffix: ` ${poolPair.data.tokenB.displaySymbol}`, usdAmount: getTokenPrice( poolPair.data.tokenB.symbol, - new BigNumber(poolPair.data.tokenB.reserve) + new BigNumber(poolPair.data.tokenB.reserve), ), usdTextStyle: tailwind("text-sm"), usdContainerStyle: tailwind("pt-1"), @@ -366,7 +366,7 @@ function PriceRateDetail({ poolPair }: { poolPair: DexItem }): JSX.Element { suffix: ` ${poolPair.data.tokenB.displaySymbol}`, usdAmount: getTokenPrice( poolPair.data.tokenB.symbol, - new BigNumber(poolPair.data.priceRatio.ba) + new BigNumber(poolPair.data.priceRatio.ba), ), usdTextStyle: tailwind("text-sm"), usdContainerStyle: tailwind("pt-1"), @@ -385,7 +385,7 @@ function PriceRateDetail({ poolPair }: { poolPair: DexItem }): JSX.Element { suffix: ` ${poolPair.data.tokenA.displaySymbol}`, usdAmount: getTokenPrice( poolPair.data.tokenA.symbol, - new BigNumber(poolPair.data.priceRatio.ab) + new BigNumber(poolPair.data.priceRatio.ab), ), usdTextStyle: tailwind("text-sm"), usdContainerStyle: tailwind("pt-1"), @@ -405,7 +405,7 @@ function YourPoolPairTokenBreakdown(props: { }): JSX.Element { const { getTokenPrice } = useTokenPrice(); const { tokenATotal, tokenBTotal } = useYourPoolPairAmountBreakdown( - props.yourLpToken + props.yourLpToken, ); return ( @@ -424,7 +424,7 @@ function YourPoolPairTokenBreakdown(props: { usdAmount: getTokenPrice( props.yourLpToken.symbol, new BigNumber(props.yourLpToken.amount), - true + true, ), usdTextStyle: tailwind("text-sm"), usdContainerStyle: tailwind("pt-1"), @@ -436,7 +436,7 @@ function YourPoolPairTokenBreakdown(props: { value: translate( "screens/PoolPairDetailsScreen", "Tokens in {{symbol}}", - { symbol: props.tokenADisplaySymbol } + { symbol: props.tokenADisplaySymbol }, ), testID: "your_lp_tokenA", }} @@ -444,7 +444,7 @@ function YourPoolPairTokenBreakdown(props: { value: tokenATotal.toFixed(8), usdAmount: getTokenPrice( props.tokenASymbol, - new BigNumber(tokenATotal) + new BigNumber(tokenATotal), ), usdTextStyle: tailwind("text-sm"), usdContainerStyle: tailwind("pt-1"), @@ -456,7 +456,7 @@ function YourPoolPairTokenBreakdown(props: { value: translate( "screens/PoolPairDetailsScreen", "Tokens in {{symbol}}", - { symbol: props.tokenBDisplaySymbol } + { symbol: props.tokenBDisplaySymbol }, ), testID: "your_lp_tokenB", }} @@ -464,7 +464,7 @@ function YourPoolPairTokenBreakdown(props: { value: tokenBTotal.toFixed(8), usdAmount: getTokenPrice( props.tokenBSymbol, - new BigNumber(tokenBTotal) + new BigNumber(tokenBTotal), ), usdTextStyle: tailwind("text-sm"), usdContainerStyle: tailwind("pt-1"), @@ -520,7 +520,7 @@ function APRDetail(props: { {translate( "screens/PoolPairDetailsScreen", "{{percentage}}% in rewards", - { percentage: val } + { percentage: val }, )} )} @@ -539,7 +539,7 @@ function APRDetail(props: { {translate( "screens/PoolPairDetailsScreen", "{{percentage}}% in commissions", - { percentage: val } + { percentage: val }, )} )} @@ -579,7 +579,7 @@ function PoolPairActionSection({ onPress={() => onAdd( pair.data, - walletToken ?? (pair.data as unknown as WalletToken) + walletToken ?? (pair.data as unknown as WalletToken), ) } isLast={walletToken === undefined} diff --git a/mobile-app/app/screens/AppNavigator/screens/Dex/components/ViewPoolDetails.tsx b/mobile-app/app/screens/AppNavigator/screens/Dex/components/ViewPoolDetails.tsx index fc5e5cd7af..a13b5aded6 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Dex/components/ViewPoolDetails.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Dex/components/ViewPoolDetails.tsx @@ -5,7 +5,7 @@ import BigNumber from "bignumber.js"; import { ThemedTextV2, ThemedViewV2 } from "@components/themed"; import { AddressToken } from "@defichain/whale-api-client/dist/api/address"; import { PoolPairData } from "@defichain/whale-api-client/dist/api/poolpairs"; -import { WalletToken } from "@waveshq/walletkit-ui/dist/store"; +import { WalletToken } from "@waveshq/walletkit-ui/store"; import { useDenominationCurrency } from "@screens/AppNavigator/screens/Portfolio/hooks/PortfolioCurrency"; import { useTokenPrice } from "@screens/AppNavigator/screens/Portfolio/hooks/TokenPrice"; import { translate } from "@translations"; @@ -40,7 +40,7 @@ export const ViewPoolDetails = ({ style={tailwind( "px-5 h-full flex flex-grow", { "-mt-0.5": Platform.OS === "ios" }, - { "-mt-1": Platform.OS === "android" } + { "-mt-1": Platform.OS === "android" }, )} > {/* -mt-1 above and mt-1 added below is kind of hack to solved React Navigation elevation bug on android for now. */} @@ -48,7 +48,7 @@ export const ViewPoolDetails = ({ style={tailwind( "mb-3 flex-row items-center", { "mt-1": Platform.OS === "ios" }, - { "mt-2": Platform.OS === "android" } + { "mt-2": Platform.OS === "android" }, )} > @@ -89,7 +89,7 @@ function AddLiquidityDetails({ }: AddLiquidityDetailsProps): JSX.Element { const { poolpairs: pairs } = useSelector((state: RootState) => state.wallet); const poolPairData = pairs.find( - (pr) => pr.data.symbol === (pairInfo as AddressToken).symbol + (pr) => pr.data.symbol === (pairInfo as AddressToken).symbol, ); const mappedPair = poolPairData?.data; const { denominationCurrency } = useDenominationCurrency(); @@ -97,7 +97,7 @@ function AddLiquidityDetails({ const getUSDValue = ( amount: BigNumber, symbol: string, - isLPs: boolean = false + isLPs: boolean = false, ): BigNumber => { return getTokenPrice(symbol, amount, isLPs); }; @@ -137,7 +137,7 @@ function AddLiquidityDetails({ }} rhs={{ value: getPrecisedTokenValue( - pairData.totalLiquidity.usd ?? new BigNumber(0) + pairData.totalLiquidity.usd ?? new BigNumber(0), ), testID: `total_liquidity_${pairInfo.displaySymbol}_amount`, usdTextStyle: tailwind("text-sm"), @@ -164,7 +164,7 @@ function AddLiquidityDetails({ usdTextStyle: tailwind("text-sm"), usdAmount: getUSDValue( new BigNumber(pairData.tokenA.reserve), - pairData.tokenA.symbol + pairData.tokenA.symbol, ), suffix: ` ${pairData.tokenA.displaySymbol}`, }} @@ -188,7 +188,7 @@ function AddLiquidityDetails({ usdTextStyle: tailwind("text-sm"), usdAmount: getUSDValue( new BigNumber(pairData.tokenB.reserve), - pairData.tokenB.symbol + pairData.tokenB.symbol, ), suffix: ` ${pairData.tokenB.displaySymbol}`, }} @@ -199,7 +199,7 @@ function AddLiquidityDetails({ state.wallet); const poolPairData = pairs.find( - (pr) => pr.data.symbol === (pairInfo as AddressToken).symbol + (pr) => pr.data.symbol === (pairInfo as AddressToken).symbol, // PoolPairData comes from token detail screen ); @@ -249,7 +249,7 @@ function RemoveLiquidityDetails({ const getUSDValue = ( amount: BigNumber, symbol: string, - isLPs: boolean = false + isLPs: boolean = false, ): BigNumber => { return getTokenPrice(symbol, amount, isLPs); }; @@ -305,7 +305,7 @@ function RemoveLiquidityDetails({ }, usdAmount: getUSDValue( new BigNumber(tokenATotal), - pairData.tokenA.symbol + pairData.tokenA.symbol, ), usdTextStyle: tailwind("text-sm"), testID: `token_in_${pairData.tokenA.displaySymbol}_value`, @@ -331,7 +331,7 @@ function RemoveLiquidityDetails({ }, usdAmount: getUSDValue( new BigNumber(tokenBTotal), - pairData.tokenB.symbol + pairData.tokenB.symbol, ), usdTextStyle: tailwind("text-sm"), testID: `token_in_${pairData.tokenB.displaySymbol}_value`, @@ -350,7 +350,7 @@ function RemoveLiquidityDetails({ }} rhs={{ value: new BigNumber( - isNaN(pairData.apr.total) ? 0 : pairData.apr.total + isNaN(pairData.apr.total) ? 0 : pairData.apr.total, ) .times(100) .toFixed(2), diff --git a/mobile-app/app/screens/AppNavigator/screens/Dex/hook/FutureSwap.ts b/mobile-app/app/screens/AppNavigator/screens/Dex/hook/FutureSwap.ts index 9cd35c6742..f866e9a038 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Dex/hook/FutureSwap.ts +++ b/mobile-app/app/screens/AppNavigator/screens/Dex/hook/FutureSwap.ts @@ -2,7 +2,7 @@ import { useFeatureFlagContext } from "@contexts/FeatureFlagContext"; import { EnvironmentNetwork } from "@waveshq/walletkit-core"; import { useNetworkContext } from "@waveshq/walletkit-ui"; import { RootState } from "@store"; -import { tokenSelectorByDisplaySymbol } from "@waveshq/walletkit-ui/dist/store"; +import { tokenSelectorByDisplaySymbol } from "@waveshq/walletkit-ui/store"; import BigNumber from "bignumber.js"; import dayjs from "dayjs"; import { useSelector } from "react-redux"; @@ -28,11 +28,14 @@ export function useFutureSwap(props: SwapType): { const fromTokenDetail = useSelector((state: RootState) => tokenSelectorByDisplaySymbol( state.wallet, - props.fromTokenDisplaySymbol ?? "" - ) + props.fromTokenDisplaySymbol ?? "", + ), ); const toTokenDetail = useSelector((state: RootState) => - tokenSelectorByDisplaySymbol(state.wallet, props.toTokenDisplaySymbol ?? "") + tokenSelectorByDisplaySymbol( + state.wallet, + props.toTokenDisplaySymbol ?? "", + ), ); const { isFeatureAvailable } = useFeatureFlagContext(); const isFutureSwapEnabled = @@ -77,7 +80,7 @@ export function useFutureSwap(props: SwapType): { export function useFutureSwapDate( executionBlock: number, - blockCount: number + blockCount: number, ): { timeRemaining: string; transactionDate: string; @@ -92,7 +95,7 @@ export function useFutureSwapDate( : 3; const blocksRemaining = BigNumber.max( executionBlock - blockCount, - 0 + 0, ).toNumber(); const blocksSeconds = blocksRemaining * secondsPerBlock; return { diff --git a/mobile-app/app/screens/AppNavigator/screens/Dex/hook/SwappableTokens.ts b/mobile-app/app/screens/AppNavigator/screens/Dex/hook/SwappableTokens.ts index 5e9d74c309..dcaa793a7f 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Dex/hook/SwappableTokens.ts +++ b/mobile-app/app/screens/AppNavigator/screens/Dex/hook/SwappableTokens.ts @@ -7,8 +7,8 @@ import { fetchDexPrice, fetchSwappableTokens, tokensSelector, -} from "@waveshq/walletkit-ui/dist/store"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +} from "@waveshq/walletkit-ui/store"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { BottomSheetToken } from "@components/BottomSheetTokenList"; import { CacheApi } from "@api/cache"; import { useNetworkContext } from "@waveshq/walletkit-ui"; @@ -28,20 +28,20 @@ export function useSwappableTokens( fromTokenId: string | undefined, fromTokenDisplaySymbol: string | undefined, fromTokenSymbol: string | undefined, - isFutureSwap: boolean + isFutureSwap: boolean, ): TokenPrice { const client = useWhaleApiClient(); const { network } = useNetworkContext(); const dispatch = useAppDispatch(); const blockCount = useSelector((state: RootState) => state.block.count); const { swappableTokens, poolpairs } = useSelector( - (state: RootState) => state.wallet + (state: RootState) => state.wallet, ); const tokens = useSelector((state: RootState) => - tokensSelector(state.wallet) + tokensSelector(state.wallet), ); const loanTokens = useSelector((state: RootState) => - loanTokensSelector(state.loans) + loanTokensSelector(state.loans), ); const [fromTokens, setFromTokens] = useState([]); @@ -60,9 +60,9 @@ export function useSwappableTokens( fetchDexPrice({ client, denomination: fromTokenSymbol ?? "USDT", - }) + }), ); - }, [blockCount, fromTokenSymbol]) + }, [blockCount, fromTokenSymbol]), ); /* Opted out of using useMemo to ensure it'll only run when screen is focused */ @@ -75,10 +75,10 @@ export function useSwappableTokens( } const hasTokenA = tokensInPair.some( - (token) => pair.data.tokenA.id === token.id + (token) => pair.data.tokenA.id === token.id, ); const hasTokenB = tokensInPair.some( - (token) => pair.data.tokenB.id === token.id + (token) => pair.data.tokenB.id === token.id, ); const tokensToAdd: TokenState[] = []; if (!hasTokenA) { @@ -90,14 +90,14 @@ export function useSwappableTokens( return [...tokensInPair, ...tokensToAdd]; }, - [] + [], ); let filterTokens = _allTokens; if (isFutureSwap) { // filter out loanTokens and DUSD filterTokens = filterTokens.filter((t) => - loanTokens.map((loan) => loan.token.id).includes(t.id) + loanTokens.map((loan) => loan.token.id).includes(t.id), ); } const swappableFromTokens: BottomSheetToken[] = filterTokens @@ -107,7 +107,7 @@ export function useSwappableTokens( return { tokenId: tokenId, available: new BigNumber( - ownedToken === undefined ? 0 : ownedToken.amount + ownedToken === undefined ? 0 : ownedToken.amount, ), token: { displaySymbol: token.displaySymbol, @@ -120,7 +120,7 @@ export function useSwappableTokens( setAllTokens(_allTokens); setFromTokens(swappableFromTokens); - }, [poolpairs, tokens, loanTokens, isFutureSwap]) + }, [poolpairs, tokens, loanTokens, isFutureSwap]), ); const toTokens = useMemo(() => { @@ -131,7 +131,7 @@ export function useSwappableTokens( if (fromTokenId !== undefined && swappableToTokens !== undefined) { CacheApi.set( cacheKey, - swappableTokens[fromTokenId === "0_unified" ? "0" : fromTokenId ?? ""] + swappableTokens[fromTokenId === "0_unified" ? "0" : fromTokenId ?? ""], ); } @@ -189,10 +189,10 @@ export function useSwappableTokens( fetchSwappableTokens({ client, fromTokenId: fromTokenId === "0_unified" ? "0" : fromTokenId, - }) + }), ); } - }, [fromTokenId]) + }, [fromTokenId]), ); return { diff --git a/mobile-app/app/screens/AppNavigator/screens/Dex/hook/YourPoolPairAmountBreakdown.ts b/mobile-app/app/screens/AppNavigator/screens/Dex/hook/YourPoolPairAmountBreakdown.ts index ccbae8d22c..c7ac131061 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Dex/hook/YourPoolPairAmountBreakdown.ts +++ b/mobile-app/app/screens/AppNavigator/screens/Dex/hook/YourPoolPairAmountBreakdown.ts @@ -1,5 +1,5 @@ import { RootState } from "@store"; -import { WalletToken } from "@waveshq/walletkit-ui/dist/store"; +import { WalletToken } from "@waveshq/walletkit-ui/store"; import BigNumber from "bignumber.js"; import { useSelector } from "react-redux"; @@ -12,7 +12,7 @@ interface AmountBreakdown { * To return estimated token breakdown for Your pool pair based on reserve of token A and B and total pool pair amount */ export function useYourPoolPairAmountBreakdown( - yourPoolPair: WalletToken + yourPoolPair: WalletToken, ): AmountBreakdown { const { poolpairs: pairs } = useSelector((state: RootState) => state.wallet); const poolPairData = pairs.find((pr) => pr.data.id === yourPoolPair.id)?.data; diff --git a/mobile-app/app/screens/AppNavigator/screens/Loans/LoansScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Loans/LoansScreen.tsx index 06ccf47a67..2ea67e035b 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Loans/LoansScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Loans/LoansScreen.tsx @@ -4,7 +4,7 @@ import { tailwind } from "@tailwind"; import { translate } from "@translations"; import { RootState } from "@store"; import { fetchLoanSchemes, fetchLoanTokens, fetchVaults } from "@store/loans"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { useWalletContext } from "@shared-contexts/WalletContext"; import { useIsFocused, useScrollToTop } from "@react-navigation/native"; import { useAppDispatch } from "@hooks/useAppDispatch"; @@ -63,7 +63,7 @@ export function LoansScreen(): JSX.Element { fetchVaults({ address, client, - }) + }), ); dispatch(fetchLoanTokens({ client })); }); @@ -81,7 +81,7 @@ export function LoansScreen(): JSX.Element { light={tailwind("bg-mono-light-v2-00 border-mono-light-v2-100")} dark={tailwind("bg-mono-dark-v2-00 border-mono-dark-v2-100")} style={tailwind( - "flex flex-col items-center pt-4 rounded-b-2xl border-b z-20" + "flex flex-col items-center pt-4 rounded-b-2xl border-b z-20", )} > diff --git a/mobile-app/app/screens/AppNavigator/screens/Loans/VaultDetail/VaultDetailScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Loans/VaultDetail/VaultDetailScreen.tsx index 1534375d28..66d5c6fb16 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Loans/VaultDetail/VaultDetailScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Loans/VaultDetail/VaultDetailScreen.tsx @@ -24,7 +24,7 @@ import { useVaultStatus } from "@screens/AppNavigator/screens/Loans/components/V import { useNextCollateralizationRatio } from "@screens/AppNavigator/screens/Loans/hooks/NextCollateralizationRatio"; import { useLoanOperations } from "@screens/AppNavigator/screens/Loans/hooks/LoanOperations"; import { useAppDispatch } from "@hooks/useAppDispatch"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { useIsFocused } from "@react-navigation/native"; import { VaultDetailStatus } from "@screens/AppNavigator/screens/Loans/VaultDetail/components/VaultDetailStatus"; import { VaultActionButtons } from "@screens/AppNavigator/screens/Loans/VaultDetail/components/VaultActionButtons"; @@ -69,27 +69,27 @@ export function VaultDetailScreen({ route, navigation }: Props): JSX.Element { const vaults = useSelector((state: RootState) => vaultsSelector(state.loans)); const loanTokens = useSelector((state: RootState) => - loanTokensSelector(state.loans) + loanTokensSelector(state.loans), ); const inLiquidation = vault?.state === LoanVaultState.IN_LIQUIDATION; const totalLoanAmount = new BigNumber( - inLiquidation || vault === undefined ? 0 : vault?.loanValue + inLiquidation || vault === undefined ? 0 : vault?.loanValue, ); const totalCollateralValue = new BigNumber( - inLiquidation || vault === undefined ? 0 : vault?.collateralValue + inLiquidation || vault === undefined ? 0 : vault?.collateralValue, ); const minColRatio = new BigNumber( - vault === undefined ? 0 : vault?.loanScheme.minColRatio + vault === undefined ? 0 : vault?.loanScheme.minColRatio, ); const vaultState = useVaultStatus( vault?.state, new BigNumber( - inLiquidation || vault === undefined ? 0 : vault?.informativeRatio + inLiquidation || vault === undefined ? 0 : vault?.informativeRatio, ), minColRatio, totalLoanAmount, - totalCollateralValue + totalCollateralValue, ); const collateralAmounts = inLiquidation || vault === undefined ? [] : vault.collateralAmounts; @@ -97,7 +97,7 @@ export function VaultDetailScreen({ route, navigation }: Props): JSX.Element { inLiquidation || vault === undefined ? [] : vault.loanAmounts; const nextCollateralizationRatio = useNextCollateralizationRatio( collateralAmounts, - loanAmounts + loanAmounts, ); const maxLoanAmount = useMaxLoan({ totalCollateralValue: totalCollateralValue, @@ -156,7 +156,7 @@ export function VaultDetailScreen({ route, navigation }: Props): JSX.Element { title: translate("components/VaultCard", "Liquidated vault"), message: translate( "screens/VaultDetailScreen", - "Vault has been liquidated, and now available for auction. View your vault on DeFiScan for more details." + "Vault has been liquidated, and now available for auction. View your vault on DeFiScan for more details.", ), buttons: [ { @@ -200,7 +200,7 @@ export function VaultDetailScreen({ route, navigation }: Props): JSX.Element { }, }), option: getBottomSheetHeader( - translate("screens/EditCollateralScreen", "Select Collateral") + translate("screens/EditCollateralScreen", "Select Collateral"), ), }, ]); @@ -209,7 +209,7 @@ export function VaultDetailScreen({ route, navigation }: Props): JSX.Element { const navigateToAddRemoveCollateralScreen = ( collateralItem: CollateralItem | BottomSheetToken, - isAdd: boolean + isAdd: boolean, ) => { const addOrRemoveParams = { vault: vault as LoanVaultActive, @@ -248,7 +248,7 @@ export function VaultDetailScreen({ route, navigation }: Props): JSX.Element { isLight, }), option: getBottomSheetHeader( - translate("components/BottomSheetLoanTokensList", "Select Token") + translate("components/BottomSheetLoanTokensList", "Select Token"), ), }, ]); @@ -270,7 +270,7 @@ export function VaultDetailScreen({ route, navigation }: Props): JSX.Element { component: BottomSheetPayBackList({ onPress: ( item: LoanVaultTokenAmount, - isPayDUSDUsingCollateral: boolean + isPayDUSDUsingCollateral: boolean, ) => { dismissModal(); navigateToPayScreen(item, isPayDUSDUsingCollateral); @@ -280,7 +280,7 @@ export function VaultDetailScreen({ route, navigation }: Props): JSX.Element { isLight: isLight, }), option: getBottomSheetHeader( - translate("screens/VaultDetailScreen", "Select Loan") + translate("screens/VaultDetailScreen", "Select Loan"), ), }, ]); @@ -289,7 +289,7 @@ export function VaultDetailScreen({ route, navigation }: Props): JSX.Element { const navigateToPayScreen = ( loanToken: LoanVaultTokenAmount, - isPayDUSDUsingCollateral: boolean + isPayDUSDUsingCollateral: boolean, ) => { navigation.navigate({ name: "PaybackLoanScreen", diff --git a/mobile-app/app/screens/AppNavigator/screens/Loans/components/AddOrRemoveCollateralForm.tsx b/mobile-app/app/screens/AppNavigator/screens/Loans/components/AddOrRemoveCollateralForm.tsx index 77a841542a..3ebf3051c5 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Loans/components/AddOrRemoveCollateralForm.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Loans/components/AddOrRemoveCollateralForm.tsx @@ -25,7 +25,7 @@ import { hasTxQueued, hasOceanTXQueued, DFITokenSelector, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { ConversionInfoText } from "@components/ConversionInfoText"; import { AmountButtonTypes, @@ -89,13 +89,13 @@ export const AddOrRemoveCollateralForm = memo( collateralTokens, } = route.params; const hasPendingJob = useSelector((state: RootState) => - hasTxQueued(state.transactionQueue) + hasTxQueued(state.transactionQueue), ); const hasPendingBroadcastJob = useSelector((state: RootState) => - hasOceanTXQueued(state.ocean) + hasOceanTXQueued(state.ocean), ); const DFIToken = useSelector((state: RootState) => - DFITokenSelector(state.wallet) + DFITokenSelector(state.wallet), ); const { isFeatureAvailable } = useFeatureFlagContext(); @@ -166,19 +166,19 @@ export const AddOrRemoveCollateralForm = memo( const initialPrices = getCollateralPrice( new BigNumber(inputValue), collateralItem, - new BigNumber(vault.collateralValue) + new BigNumber(vault.collateralValue), ); const totalCalculatedCollateralValue = isAdd ? new BigNumber(totalCollateralVaultValue).plus( - initialPrices?.collateralPrice + initialPrices?.collateralPrice, ) : new BigNumber(totalCollateralVaultValue).minus( - initialPrices.collateralPrice + initialPrices.collateralPrice, ); const prices = getCollateralPrice( totalAmount, collateralItem, - totalCalculatedCollateralValue + totalCalculatedCollateralValue, ); const { requiredVaultShareTokens, @@ -190,10 +190,10 @@ export const AddOrRemoveCollateralForm = memo( totalCalculatedCollateralValue, new BigNumber(vault.loanValue), token.id, - totalAmount + totalAmount, ); const isValidCollateralRatio = requiredTokensShare?.gte( - minRequiredTokensShare + minRequiredTokensShare, ); const removeMaxCollateralAmount = !isAdd && @@ -246,7 +246,7 @@ export const AddOrRemoveCollateralForm = memo( `How much {{symbol}} to ${isAdd ? "add" : "remove"}?`, { symbol: token.displaySymbol, - } + }, )} {onCloseButtonPress !== undefined && ( @@ -276,7 +276,7 @@ export const AddOrRemoveCollateralForm = memo( displayType="text" suffix={`% ${translate( "components/AddOrRemoveCollateralForm", - "collateral factor" + "collateral factor", )}`} renderText={(value) => ( {translate( "components/AddOrRemoveCollateralForm", - "Vault requirement" + "Vault requirement", )} @@ -481,7 +481,7 @@ export const AddOrRemoveCollateralForm = memo( {translate( "components/AddOrRemoveCollateralForm", - "Resulting collateralization" + "Resulting collateralization", )} {hasInvalidColRatio ? ( @@ -533,7 +533,7 @@ export const AddOrRemoveCollateralForm = memo( } label={translate( "components/AddOrRemoveCollateralForm", - isAdd ? "ADD TOKEN AS COLLATERAL" : "REMOVE COLLATERAL AMOUNT" + isAdd ? "ADD TOKEN AS COLLATERAL" : "REMOVE COLLATERAL AMOUNT", )} onPress={() => onButtonPress({ @@ -557,7 +557,7 @@ export const AddOrRemoveCollateralForm = memo( > {translate( "screens/BorrowLoanTokenScreen", - "Your vault needs at least 50% of DFI and/or DUSD as collateral" + "Your vault needs at least 50% of DFI and/or DUSD as collateral", )} )} @@ -568,12 +568,12 @@ export const AddOrRemoveCollateralForm = memo( > {translate( "components/AddOrRemoveCollateralForm", - "The collateral factor determines the degree of contribution of each collateral token." + "The collateral factor determines the degree of contribution of each collateral token.", )} ); - } + }, ); function ColorBar(props: { diff --git a/mobile-app/app/screens/AppNavigator/screens/Loans/components/VaultCard.test.tsx b/mobile-app/app/screens/AppNavigator/screens/Loans/components/VaultCard.test.tsx index 99a09cf349..3464dfc55b 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Loans/components/VaultCard.test.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Loans/components/VaultCard.test.tsx @@ -1,7 +1,7 @@ import { render } from "@testing-library/react-native"; import { LoanVaultState } from "@defichain/whale-api-client/dist/api/loan"; import { configureStore } from "@reduxjs/toolkit"; -import { wallet } from "@waveshq/walletkit-ui/dist/store"; +import { wallet } from "@waveshq/walletkit-ui/store"; import { loans } from "@store/loans"; import { RootState } from "@store"; import { Provider } from "react-redux"; @@ -10,7 +10,7 @@ import { VaultCard, VaultCardProps } from "./VaultCard"; jest.mock("react-native-reanimated", () => "react-native-reanimated/mock"); jest.mock( "react-native-circular-progress-indicator", - () => "react-native-circular-progress-indicator/mock" + () => "react-native-circular-progress-indicator/mock", ); jest.mock("@shared-contexts/DeFiScanContext"); @@ -108,7 +108,7 @@ describe("Vault card", () => { vault={lockedVault.vault} testID={lockedVault.testID} /> - + , ); expect(rendered.toJSON()).toMatchSnapshot(); }); @@ -143,7 +143,7 @@ describe("Vault card", () => { const rendered = render( - + , ); expect(rendered.toJSON()).toMatchSnapshot(); }); @@ -187,7 +187,7 @@ describe("Vault card", () => { vault={safeVault.vault} testID={safeVault.testID} /> - + , ); expect(rendered.toJSON()).toMatchSnapshot(); }); @@ -231,7 +231,7 @@ describe("Vault card", () => { vault={newVault.vault} testID={newVault.testID} /> - + , ); expect(rendered.toJSON()).toMatchSnapshot(); }); diff --git a/mobile-app/app/screens/AppNavigator/screens/Loans/components/Vaults.tsx b/mobile-app/app/screens/AppNavigator/screens/Loans/components/Vaults.tsx index bf15c95a7e..a4008c9a09 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Loans/components/Vaults.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Loans/components/Vaults.tsx @@ -14,7 +14,7 @@ import { LoanVault, vaultsSelector, } from "@store/loans"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { useWalletContext } from "@shared-contexts/WalletContext"; import { NavigationProp, @@ -60,7 +60,7 @@ export function Vaults(props: VaultsProps): JSX.Element { const blockCount = useSelector((state: RootState) => state.block.count); const vaults = useSelector((state: RootState) => vaultsSelector(state.loans)); const { hasFetchedVaultsData } = useSelector( - (state: RootState) => state.loans + (state: RootState) => state.loans, ); const [searchString, setSearchString] = useState(""); @@ -152,7 +152,7 @@ export function Vaults(props: VaultsProps): JSX.Element { @@ -169,7 +169,7 @@ export function Vaults(props: VaultsProps): JSX.Element { fetchVaults({ address, client, - }) + }), ); } }, [blockCount, address, isFocused]); @@ -259,7 +259,7 @@ export function Vaults(props: VaultsProps): JSX.Element { : translate( "screens/LoansScreen", "Search results for “{{searchTerm}}”", - { searchTerm: debouncedSearchTerm } + { searchTerm: debouncedSearchTerm }, )} )} @@ -324,7 +324,7 @@ function CreateVaultButton(props: { onPress: () => void }): JSX.Element { return ( void }): JSX.Element { function filterVaultsBySearchTerm( vaults: LoanVault[], searchTerm: string, - isFocused: boolean + isFocused: boolean, ): LoanVault[] { if (searchTerm === "") { return isFocused ? [] : vaults; @@ -358,7 +358,7 @@ function filterVaultsBySearchTerm( // ? vault.collateralAmounts.map((value) => value.displaySymbol) // : []; return [t.vaultId].some((searchItem) => - searchItem.toLowerCase().includes(searchTerm.trim().toLowerCase()) + searchItem.toLowerCase().includes(searchTerm.trim().toLowerCase()), ); }); } diff --git a/mobile-app/app/screens/AppNavigator/screens/Loans/hooks/CollateralTokenList.ts b/mobile-app/app/screens/AppNavigator/screens/Loans/hooks/CollateralTokenList.ts index 023543eb31..3be0bb555d 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Loans/hooks/CollateralTokenList.ts +++ b/mobile-app/app/screens/AppNavigator/screens/Loans/hooks/CollateralTokenList.ts @@ -1,6 +1,6 @@ import { createSelector } from "@reduxjs/toolkit"; import { RootState } from "@store"; -import { tokensSelector } from "@waveshq/walletkit-ui/dist/store"; +import { tokensSelector } from "@waveshq/walletkit-ui/store"; import BigNumber from "bignumber.js"; import { useSelector } from "react-redux"; import { getActivePrice } from "../../Auctions/helpers/ActivePrice"; @@ -8,7 +8,7 @@ import { CollateralItem } from "../screens/EditCollateralScreen"; export function useCollateralTokenList() { const tokens = useSelector((state: RootState) => - tokensSelector(state.wallet) + tokensSelector(state.wallet), ); const getTokenAmount = (tokenId: string): BigNumber => { @@ -17,9 +17,9 @@ export function useCollateralTokenList() { const reservedDFI = 0.1; return BigNumber.max( new BigNumber(_token === undefined ? 0 : _token.amount).minus( - _token?.id === "0_unified" ? reservedDFI : 0 + _token?.id === "0_unified" ? reservedDFI : 0, ), - 0 + 0, ); }; @@ -40,14 +40,14 @@ export function useCollateralTokenList() { collateralItem.activePrice, collateralItem.factor, "ACTIVE", - "COLLATERAL" - ) - ).gt(0) + "COLLATERAL", + ), + ).gt(0), ) - .sort((a, b) => b.available.minus(a.available).toNumber()) + .sort((a, b) => b.available.minus(a.available).toNumber()), ); const collateralTokens: CollateralItem[] = useSelector((state: RootState) => - collateralSelector(state) + collateralSelector(state), ); return { diff --git a/mobile-app/app/screens/AppNavigator/screens/Loans/hooks/LoanPaymentTokenRate.ts b/mobile-app/app/screens/AppNavigator/screens/Loans/hooks/LoanPaymentTokenRate.ts index 1c8d8d585d..f39b376311 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Loans/hooks/LoanPaymentTokenRate.ts +++ b/mobile-app/app/screens/AppNavigator/screens/Loans/hooks/LoanPaymentTokenRate.ts @@ -6,7 +6,7 @@ import { tokenSelectorByDisplaySymbol, tokensSelector, WalletToken, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { TokenData } from "@defichain/whale-api-client/dist/api/tokens"; import { useFeatureFlagContext } from "@contexts/FeatureFlagContext"; import { getActivePrice } from "../../Auctions/helpers/ActivePrice"; @@ -43,13 +43,13 @@ export const useLoanPaymentTokenRate = (props: { getPaymentPenalty: (paymentTokenSymbol: string) => BigNumber; } => { const tokens = useSelector((state: RootState) => - tokensSelector(state.wallet) + tokensSelector(state.wallet), ); const DUSDToken = useSelector((state: RootState) => - tokenSelectorByDisplaySymbol(state.wallet, "DUSD") + tokenSelectorByDisplaySymbol(state.wallet, "DUSD"), ); const paymentTokenActivePrices = useSelector((state: RootState) => - loanPaymentTokenActivePrices(state.loans) + loanPaymentTokenActivePrices(state.loans), ); const { isFeatureAvailable } = useFeatureFlagContext(); const isDUSDPaymentEnabled = isFeatureAvailable("dusd_loan_payment"); @@ -60,7 +60,7 @@ export const useLoanPaymentTokenRate = (props: { props.loanTokenBalance, tokens, DUSDToken, - isDUSDPaymentEnabled + isDUSDPaymentEnabled, ); const getPaymentPenalty = (paymentTokenSymbol: string): BigNumber => { @@ -82,13 +82,13 @@ export const useLoanPaymentTokenRate = (props: { if (paymentTokenSymbol === props.loanToken.symbol) { return BigNumber.max( BigNumber.min(penaltyOfOutstandingBalance, penaltyOfAmountToPay), - 0 + 0, ); } return BigNumber.max( BigNumber.min(penaltyOfAmountToPay, penaltyOfOutstandingBalance), - 0 + 0, ); }; @@ -96,29 +96,30 @@ export const useLoanPaymentTokenRate = (props: { const paymentTokenAmounts = paymentTokens.map((paymentToken) => { const paymentTokenActivePriceInUSD = getActivePrice( paymentToken.tokenSymbol ?? "", - paymentTokenActivePrices[`${paymentToken.tokenSymbol}-USD`] ?? undefined + paymentTokenActivePrices[`${paymentToken.tokenSymbol}-USD`] ?? + undefined, ); const paymentTokenConversionRate = paymentToken.tokenSymbol === props.loanToken.symbol ? new BigNumber(1) : new BigNumber(props.loanTokenAmountActivePriceInUSD).div( - paymentTokenActivePriceInUSD + paymentTokenActivePriceInUSD, ); const loanTokenConversionRate = paymentToken.tokenSymbol === props.loanToken.symbol ? new BigNumber(1) : new BigNumber(paymentTokenActivePriceInUSD).div( - props.loanTokenAmountActivePriceInUSD + props.loanTokenAmountActivePriceInUSD, ); const amountToPayInLoanToken = props.amountToPay.multipliedBy( - loanTokenConversionRate + loanTokenConversionRate, ); const outstandingBalanceInLoanToken = props.outstandingBalance.multipliedBy(loanTokenConversionRate); const cappedAmountInLoanToken = BigNumber.min( props.loanTokenBalance, - outstandingBalanceInLoanToken + outstandingBalanceInLoanToken, ); // Payment Token @@ -127,7 +128,7 @@ export const useLoanPaymentTokenRate = (props: { props.outstandingBalance.multipliedBy(paymentTokenConversionRate); const cappedAmountInPaymentToken = BigNumber.min( paymentToken.tokenBalance, - outstandingBalanceInPaymentToken + outstandingBalanceInPaymentToken, ); return { @@ -158,7 +159,7 @@ const _getPaymentTokens = ( tokenBalance: BigNumber, tokens: WalletToken[], DUSDToken: TokenData | undefined, - isDUSDPaymentEnabled: boolean + isDUSDPaymentEnabled: boolean, ): PaymentTokenProps[] => { const paymentTokens = [ { @@ -202,12 +203,12 @@ const _getPaymentTokens = ( export const getTokenAmount = ( tokenId: string, - tokens: WalletToken[] + tokens: WalletToken[], ): BigNumber => { const reservedDFI = 0.1; const id = tokenId === "0" ? "0_unified" : tokenId; const tokenAmount = new BigNumber( - tokens.find((t) => t.id === id)?.amount ?? 0 + tokens.find((t) => t.id === id)?.amount ?? 0, ); return id === "0_unified" diff --git a/mobile-app/app/screens/AppNavigator/screens/Loans/screens/AddOrRemoveCollateralScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Loans/screens/AddOrRemoveCollateralScreen.tsx index 8dd2f6185f..93de0f1386 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Loans/screens/AddOrRemoveCollateralScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Loans/screens/AddOrRemoveCollateralScreen.tsx @@ -18,7 +18,7 @@ import { hasOceanTXQueued, DFITokenSelector, DFIUtxoSelector, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { getPrecisedCurrencyValue, getPrecisedTokenValue, @@ -47,7 +47,7 @@ import { import { CollateralFactorTag } from "@components/CollateralFactorTag"; import { TextRowV2 } from "@components/TextRowV2"; import { NumberRowV2 } from "@components/NumberRowV2"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { useLogger } from "@shared-contexts/NativeLoggingProvider"; import { useAppDispatch } from "@hooks/useAppDispatch"; import { queueConvertTransaction } from "@hooks/wallet/Conversion"; diff --git a/mobile-app/app/screens/AppNavigator/screens/Loans/screens/BorrowLoanTokenScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Loans/screens/BorrowLoanTokenScreen.tsx index 2ef12bd051..807b6a06dd 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Loans/screens/BorrowLoanTokenScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Loans/screens/BorrowLoanTokenScreen.tsx @@ -18,14 +18,11 @@ import { LoanToken, LoanVaultActive, } from "@defichain/whale-api-client/dist/api/loan"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { useLogger } from "@shared-contexts/NativeLoggingProvider"; import { useSelector } from "react-redux"; import { RootState } from "@store"; -import { - hasTxQueued, - hasOceanTXQueued, -} from "@waveshq/walletkit-ui/dist/store"; +import { hasTxQueued, hasOceanTXQueued } from "@waveshq/walletkit-ui/store"; import { useWalletContext } from "@shared-contexts/WalletContext"; import { getActivePrice } from "@screens/AppNavigator/screens/Auctions/helpers/ActivePrice"; import { getPrecisedCurrencyValue } from "@screens/AppNavigator/screens/Auctions/helpers/precision-token-value"; diff --git a/mobile-app/app/screens/AppNavigator/screens/Loans/screens/CloseVaultScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Loans/screens/CloseVaultScreen.tsx index 9c99e56267..10876a790c 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Loans/screens/CloseVaultScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Loans/screens/CloseVaultScreen.tsx @@ -10,7 +10,7 @@ import { hasOceanTXQueued, hasTxQueued, transactionQueue, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { onTransactionBroadcast } from "@api/transaction/transaction_commands"; import { WhaleWalletAccount } from "@defichain/whale-api-wallet"; import { CTransactionSegWit } from "@defichain/jellyfish-transaction/dist"; @@ -39,10 +39,10 @@ type Props = StackScreenProps; export function CloseVaultScreen({ route, navigation }: Props): JSX.Element { const { vaultId } = route.params; const hasPendingJob = useSelector((state: RootState) => - hasTxQueued(state.transactionQueue) + hasTxQueued(state.transactionQueue), ); const hasPendingBroadcastJob = useSelector((state: RootState) => - hasOceanTXQueued(state.ocean) + hasOceanTXQueued(state.ocean), ); const dispatch = useAppDispatch(); const logger = useLogger(); @@ -62,7 +62,7 @@ export function CloseVaultScreen({ route, navigation }: Props): JSX.Element { onTransactionBroadcast(isOnPage, navigation.dispatch); }, () => {}, - logger + logger, ); } @@ -75,7 +75,7 @@ export function CloseVaultScreen({ route, navigation }: Props): JSX.Element { const truncatedVaultId = `${vaultId.substring(0, 3)}...${vaultId.substring( vaultId.length - 3, - vaultId.length + vaultId.length, )}`; return ( @@ -97,7 +97,7 @@ export function CloseVaultScreen({ route, navigation }: Props): JSX.Element { /> {translate( @@ -105,7 +105,7 @@ export function CloseVaultScreen({ route, navigation }: Props): JSX.Element { "Are you sure you want to close your vault {{truncatedVaultId}}?", { truncatedVaultId, - } + }, )} @@ -120,7 +120,7 @@ export function CloseVaultScreen({ route, navigation }: Props): JSX.Element { > {translate( "screens/CloseVaultScreen", - "All remaining collaterals will be returned to your wallet." + "All remaining collaterals will be returned to your wallet.", )} @@ -254,11 +254,11 @@ async function closeVault( dispatch: Dispatch, onBroadcast: () => void, onConfirmation: () => void, - logger: NativeLoggingProps + logger: NativeLoggingProps, ): Promise { try { const signer = async ( - account: WhaleWalletAccount + account: WhaleWalletAccount, ): Promise => { const script = await account.getScript(); const builder = account.withTransactionBuilder(); @@ -267,14 +267,14 @@ async function closeVault( vaultId: vaultId, to: script, }, - script + script, ); return new CTransactionSegWit(signed); }; const truncatedVaultId = `${vaultId.substring(0, 3)}...${vaultId.substring( vaultId.length - 3, - vaultId.length + vaultId.length, )}`; dispatch( @@ -285,29 +285,29 @@ async function closeVault( "Closing vault {{vaultId}}", { vaultId: truncatedVaultId, - } + }, ), drawerMessages: { preparing: translate( "screens/OceanInterface", - "Preparing to close vault…" + "Preparing to close vault…", ), waiting: translate( "screens/CloseVaultScreen", "Closing vault {{vaultId}}", { vaultId: truncatedVaultId, - } + }, ), complete: translate( "screens/CloseVaultScreen", "Closed vault {{vaultId}}", - { vaultId: truncatedVaultId } + { vaultId: truncatedVaultId }, ), }, onBroadcast, onConfirmation, - }) + }), ); } catch (e) { logger.error(e); diff --git a/mobile-app/app/screens/AppNavigator/screens/Loans/screens/ConfirmBorrowLoanTokenScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Loans/screens/ConfirmBorrowLoanTokenScreen.tsx index a411b4c272..fd168abcd8 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Loans/screens/ConfirmBorrowLoanTokenScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Loans/screens/ConfirmBorrowLoanTokenScreen.tsx @@ -14,7 +14,7 @@ import { hasOceanTXQueued, transactionQueue, AddressType, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { StackScreenProps } from "@react-navigation/stack"; import { NativeLoggingProps, @@ -29,7 +29,7 @@ import { import { onTransactionBroadcast } from "@api/transaction/transaction_commands"; import { fetchVaults } from "@store/loans"; import { useWalletContext } from "@shared-contexts/WalletContext"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { getPrecisedCurrencyValue } from "@screens/AppNavigator/screens/Auctions/helpers/precision-token-value"; import { useAppDispatch } from "@hooks/useAppDispatch"; import { SummaryTitle } from "@components/SummaryTitle"; @@ -56,10 +56,10 @@ export function ConfirmBorrowLoanTokenScreen({ resultingColRatio, } = route.params; const hasPendingJob = useSelector((state: RootState) => - hasTxQueued(state.transactionQueue) + hasTxQueued(state.transactionQueue), ); const hasPendingBroadcastJob = useSelector((state: RootState) => - hasOceanTXQueued(state.ocean) + hasOceanTXQueued(state.ocean), ); const dispatch = useAppDispatch(); const logger = useLogger(); @@ -88,10 +88,10 @@ export function ConfirmBorrowLoanTokenScreen({ fetchVaults({ address, client, - }) + }), ); }, - logger + logger, ); } @@ -108,7 +108,7 @@ export function ConfirmBorrowLoanTokenScreen({ amount={new BigNumber(borrowAmount)} title={translate( "screens/ConfirmBorrowLoanTokenScreen", - "You are borrowing" + "You are borrowing", )} testID="text_borrow_amount" iconA={loanToken.token.displaySymbol} @@ -117,7 +117,7 @@ export function ConfirmBorrowLoanTokenScreen({ addressType={AddressType.WalletAddress} customToAddressTitle={translate( "screens/ConfirmBorrowLoanTokenScreen", - "On" + "On", )} /> @@ -137,7 +137,7 @@ export function ConfirmBorrowLoanTokenScreen({ > {translate( "screens/ConfirmBorrowLoanTokenScreen", - "Prices may vary during transaction confirmation." + "Prices may vary during transaction confirmation.", )} , onBroadcast: () => void, onConfirmation: () => void, - logger: NativeLoggingProps + logger: NativeLoggingProps, ): Promise { try { const signer = async ( - account: WhaleWalletAccount + account: WhaleWalletAccount, ): Promise => { const script = await account.getScript(); const builder = account.withTransactionBuilder(); @@ -369,7 +369,7 @@ async function borrowLoanToken( }, ], }, - script + script, ); return new CTransactionSegWit(signed); }; @@ -385,9 +385,9 @@ async function borrowLoanToken( symbol: loanToken.token.displaySymbol, vaultId: `${vaultId.slice(0, 4)}...${vaultId.slice( vaultId.length - 4, - vaultId.length + vaultId.length, )}`, - } + }, ), drawerMessages: { preparing: translate("screens/OceanInterface", "Preparing loan…"), @@ -397,7 +397,7 @@ async function borrowLoanToken( { amount: borrowAmount.toFixed(8), symbol: loanToken.token.displaySymbol, - } + }, ), complete: translate( "screens/OceanInterface", @@ -405,12 +405,12 @@ async function borrowLoanToken( { amount: borrowAmount.toFixed(8), symbol: loanToken.token.displaySymbol, - } + }, ), }, onBroadcast, onConfirmation, - }) + }), ); } catch (e) { logger.error(e); diff --git a/mobile-app/app/screens/AppNavigator/screens/Loans/screens/ConfirmEditCollateralScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Loans/screens/ConfirmEditCollateralScreen.tsx index 33c9893c56..02e67bb59b 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Loans/screens/ConfirmEditCollateralScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Loans/screens/ConfirmEditCollateralScreen.tsx @@ -13,7 +13,7 @@ import { hasOceanTXQueued, transactionQueue, AddressType, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { TokenData } from "@defichain/whale-api-client/dist/api/tokens"; import { NativeLoggingProps, @@ -28,7 +28,7 @@ import { getCollateralValue } from "@screens/AppNavigator/screens/Loans/hooks/Co import { onTransactionBroadcast } from "@api/transaction/transaction_commands"; import { fetchVaults } from "@store/loans"; import { useWalletContext } from "@shared-contexts/WalletContext"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { getPrecisedCurrencyValue } from "@screens/AppNavigator/screens/Auctions/helpers/precision-token-value"; import { useAppDispatch } from "@hooks/useAppDispatch"; import { SummaryTitle } from "@components/SummaryTitle"; @@ -63,13 +63,13 @@ export function ConfirmEditCollateralScreen({ const addressLabel = useAddressLabel(address); const client = useWhaleApiClient(); const hasPendingJob = useSelector((state: RootState) => - hasTxQueued(state.transactionQueue) + hasTxQueued(state.transactionQueue), ); const hasPendingBroadcastJob = useSelector((state: RootState) => - hasOceanTXQueued(state.ocean) + hasOceanTXQueued(state.ocean), ); const currentBroadcastJob = useSelector((state: RootState) => - firstTransactionSelector(state.ocean) + firstTransactionSelector(state.ocean), ); const [isConverting, setIsConverting] = useState(false); @@ -103,7 +103,7 @@ export function ConfirmEditCollateralScreen({ title: translate("screens/Settings", "Cancel transaction"), message: translate( "screens/Settings", - "By cancelling, you will lose any changes you made for your transaction." + "By cancelling, you will lose any changes you made for your transaction.", ), buttons: [ { @@ -147,9 +147,9 @@ export function ConfirmEditCollateralScreen({ fetchVaults({ address, client, - }) + }), ); - } + }, ); } @@ -176,7 +176,7 @@ export function ConfirmEditCollateralScreen({ @@ -195,14 +195,14 @@ export function ConfirmEditCollateralScreen({ @@ -328,7 +328,7 @@ export function ConfirmEditCollateralScreen({ lhs={{ value: translate( "screens/AddOrRemoveCollateralScreen", - "Max loan amount" + "Max loan amount", ), testID: "confirm_edit_max_loan", themedProps: lhsThemedProps, @@ -343,14 +343,14 @@ export function ConfirmEditCollateralScreen({ {translate( "screens/ConfirmEditCollateralScreen", - "Prices may vary during transaction confirmation." + "Prices may vary during transaction confirmation.", )} )} @@ -387,7 +387,7 @@ export function ConfirmEditCollateralScreen({ isDisabled={hasPendingJob || hasPendingBroadcastJob} label={translate( "screens/ConfirmEditCollateralScreen", - isAdd ? "Add collateral" : "Remove collateral" + isAdd ? "Add collateral" : "Remove collateral", )} onSubmit={onSubmit} onCancel={onCancel} @@ -412,11 +412,11 @@ async function modifyCollateral( dispatch: Dispatch, logger: NativeLoggingProps, onBroadcast: () => void, - onConfirmation: () => void + onConfirmation: () => void, ): Promise { try { const signer = async ( - account: WhaleWalletAccount + account: WhaleWalletAccount, ): Promise => { const script = await account.getScript(); const builder = account.withTransactionBuilder(); @@ -431,7 +431,7 @@ async function modifyCollateral( amount: tokenAmount, }, }, - script + script, ) : await builder.loans.withdrawFromVault( { @@ -442,7 +442,7 @@ async function modifyCollateral( }, to: script, }, - script + script, ); return new CTransactionSegWit(signed); }; @@ -458,7 +458,7 @@ async function modifyCollateral( { amount: tokenAmount.toFixed(8), symbol: token.displaySymbol, - } + }, ), drawerMessages: { preparing: translate( @@ -469,7 +469,7 @@ async function modifyCollateral( { amount: tokenAmount.toFixed(8), symbol: token.displaySymbol, - } + }, ), waiting: translate( "screens/ConfirmEditCollateralScreen", @@ -479,7 +479,7 @@ async function modifyCollateral( { amount: tokenAmount.toFixed(8), symbol: token.displaySymbol, - } + }, ), complete: translate( "screens/ConfirmEditCollateralScreen", @@ -489,12 +489,12 @@ async function modifyCollateral( { amount: tokenAmount.toFixed(8), symbol: token.displaySymbol, - } + }, ), }, onConfirmation, onBroadcast, - }) + }), ); } catch (e) { logger.error(e); diff --git a/mobile-app/app/screens/AppNavigator/screens/Loans/screens/ConfirmEditLoanSchemeScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Loans/screens/ConfirmEditLoanSchemeScreen.tsx index 45e52bab30..c1a8609873 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Loans/screens/ConfirmEditLoanSchemeScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Loans/screens/ConfirmEditLoanSchemeScreen.tsx @@ -17,7 +17,7 @@ import { hasTxQueued, hasOceanTXQueued, transactionQueue, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { LoanScheme } from "@defichain/whale-api-client/dist/api/loan"; import { NativeLoggingProps, @@ -44,10 +44,10 @@ export function ConfirmEditLoanSchemeScreen({ // Submit const hasPendingJob = useSelector((state: RootState) => - hasTxQueued(state.transactionQueue) + hasTxQueued(state.transactionQueue), ); const hasPendingBroadcastJob = useSelector((state: RootState) => - hasOceanTXQueued(state.ocean) + hasOceanTXQueued(state.ocean), ); const dispatch = useAppDispatch(); const logger = useLogger(); @@ -76,7 +76,7 @@ export function ConfirmEditLoanSchemeScreen({ onTransactionBroadcast(isOnPage, navigation.dispatch); }, () => {}, - logger + logger, ); } @@ -134,7 +134,7 @@ function SummaryHeader(props: { > {translate( "screens/ConfirmEditLoanSchemeScreen", - "You are editing loan scheme of" + "You are editing loan scheme of", )} @@ -191,7 +191,7 @@ interface SummaryTransactionDetailsProps { } function SummaryTransactionDetails( - props: SummaryTransactionDetailsProps + props: SummaryTransactionDetailsProps, ): JSX.Element { return ( @@ -204,7 +204,7 @@ function SummaryTransactionDetails( lhs={{ value: translate( "screens/ConfirmEditLoanSchemeScreen", - "Prev. min. collateral ratio" + "Prev. min. collateral ratio", ), testID: "prev_min_col_ratio_label", themedProps: { @@ -223,7 +223,7 @@ function SummaryTransactionDetails( lhs={{ value: translate( "screens/ConfirmEditLoanSchemeScreen", - "Prev. interest" + "Prev. interest", ), testID: "prev_vault_interest_label", themedProps: { @@ -248,7 +248,7 @@ function SummaryTransactionDetails( lhs={{ value: translate( "screens/ConfirmEditLoanSchemeScreen", - "New min. collateral ratio" + "New min. collateral ratio", ), testID: "new_min_col_ratio_label", themedProps: { @@ -267,7 +267,7 @@ function SummaryTransactionDetails( lhs={{ value: translate( "screens/ConfirmEditLoanSchemeScreen", - "New vault interest" + "New vault interest", ), testID: "new_vault_interest_label", themedProps: { @@ -292,7 +292,7 @@ function SummaryTransactionDetails( lhs={{ value: translate( "screens/ConfirmEditLoanSchemeScreen", - "Transaction fee" + "Transaction fee", ), themedProps: { light: tailwind("text-mono-light-v2-500"), @@ -324,11 +324,11 @@ async function editLoanScheme( dispatch: Dispatch, onBroadcast: () => void, onConfirmation: () => void, - logger: NativeLoggingProps + logger: NativeLoggingProps, ): Promise { try { const signer = async ( - account: WhaleWalletAccount + account: WhaleWalletAccount, ): Promise => { const script = await account.getScript(); const builder = account.withTransactionBuilder(); @@ -338,7 +338,7 @@ async function editLoanScheme( ownerAddress: script, schemeId: loanScheme.id, }, - script + script, ); return new CTransactionSegWit(signed); }; @@ -346,7 +346,7 @@ async function editLoanScheme( const truncatedVaultIdFront = `${vaultId.substring(0, 3)}`; const truncatedVaultIdBack = `${vaultId.substring( vaultId.length - 3, - vaultId.length + vaultId.length, )}`; dispatch( @@ -357,7 +357,7 @@ async function editLoanScheme( "Editing vault {{vaultId}}", { vaultId: `${truncatedVaultIdFront}...${truncatedVaultIdBack}`, - } + }, ), drawerMessages: { waiting: translate( @@ -365,19 +365,19 @@ async function editLoanScheme( "Editing vault {{vaultId}}", { vaultId: `${truncatedVaultIdFront}...${truncatedVaultIdBack}`, - } + }, ), complete: translate( "screens/OceanInterface", "Edited vault {{vaultId}}", { vaultId: `${truncatedVaultIdFront}...${truncatedVaultIdBack}`, - } + }, ), }, onBroadcast, onConfirmation, - }) + }), ); } catch (e) { logger.error(e); diff --git a/mobile-app/app/screens/AppNavigator/screens/Loans/screens/ConfirmPaybackLoanScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Loans/screens/ConfirmPaybackLoanScreen.tsx index 131a9632f5..709e6df15c 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Loans/screens/ConfirmPaybackLoanScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Loans/screens/ConfirmPaybackLoanScreen.tsx @@ -14,7 +14,7 @@ import { hasTxQueued, hasOceanTXQueued, transactionQueue, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { StackScreenProps } from "@react-navigation/stack"; import { NativeLoggingProps, @@ -26,7 +26,7 @@ import { LoanVaultTokenAmount } from "@defichain/whale-api-client/dist/api/loan" import { onTransactionBroadcast } from "@api/transaction/transaction_commands"; import { fetchVaults } from "@store/loans"; import { useWalletContext } from "@shared-contexts/WalletContext"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { useAppDispatch } from "@hooks/useAppDispatch"; import { SummaryTitle } from "@components/SummaryTitle"; import { useAddressLabel } from "@hooks/useAddressLabel"; @@ -53,10 +53,10 @@ export function ConfirmPaybackLoanScreen({ loanTokenActivePriceInUSD, } = route.params; const hasPendingJob = useSelector((state: RootState) => - hasTxQueued(state.transactionQueue) + hasTxQueued(state.transactionQueue), ); const hasPendingBroadcastJob = useSelector((state: RootState) => - hasOceanTXQueued(state.ocean) + hasOceanTXQueued(state.ocean), ); const dispatch = useAppDispatch(); const { address } = useWalletContext(); @@ -93,10 +93,10 @@ export function ConfirmPaybackLoanScreen({ fetchVaults({ address, client, - }) + }), ); }, - logger + logger, ); } @@ -110,7 +110,7 @@ export function ConfirmPaybackLoanScreen({ const addressLabel = useAddressLabel(address); const loanRemaining = BigNumber.max( 0, - new BigNumber(loanTokenAmount.amount).minus(amountToPay) + new BigNumber(loanTokenAmount.amount).minus(amountToPay), ); return ( @@ -119,7 +119,7 @@ export function ConfirmPaybackLoanScreen({ amount={amountToPay} title={translate( "screens/ConfirmPaybackLoanScreen", - "You are paying" + "You are paying", )} testID="text_send_amount" iconA={loanTokenAmount.displaySymbol} @@ -131,7 +131,7 @@ export function ConfirmPaybackLoanScreen({ {translate( "screens/ConfirmPaybackLoanScreen", - "Prices may vary during transaction confirmation." + "Prices may vary during transaction confirmation.", )} , onBroadcast: () => void, onConfirmation: () => void, - logger: NativeLoggingProps + logger: NativeLoggingProps, ): Promise { try { const signer = async ( - account: WhaleWalletAccount + account: WhaleWalletAccount, ): Promise => { const script = await account.getScript(); const builder = account.withTransactionBuilder(); @@ -333,7 +333,7 @@ async function paybackLoanToken( }, ], }, - script + script, ); return new CTransactionSegWit(signed); }; @@ -347,12 +347,12 @@ async function paybackLoanToken( { amountToPay: amountToPay.toFixed(8), symbol: loanToken.displaySymbol, - } + }, ), drawerMessages: { preparing: translate( "screens/OceanInterface", - "Preparing loan payment…" + "Preparing loan payment…", ), waiting: translate( "screens/ConfirmPaybackLoanScreen", @@ -360,7 +360,7 @@ async function paybackLoanToken( { amountToPay: amountToPay.toFixed(8), symbol: loanToken.displaySymbol, - } + }, ), complete: translate( "screens/ConfirmPaybackLoanScreen", @@ -368,12 +368,12 @@ async function paybackLoanToken( { amountToPay: amountToPay.toFixed(8), symbol: loanToken.displaySymbol, - } + }, ), }, onBroadcast, onConfirmation, - }) + }), ); } catch (e) { logger.error(e); diff --git a/mobile-app/app/screens/AppNavigator/screens/Loans/screens/CreateVaultScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Loans/screens/CreateVaultScreen.tsx index 2c11aef1a5..4ea8ce8279 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Loans/screens/CreateVaultScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Loans/screens/CreateVaultScreen.tsx @@ -1,7 +1,7 @@ import { View } from "@components"; import { ThemedScrollViewV2, ThemedTextV2 } from "@components/themed"; import { StackScreenProps } from "@react-navigation/stack"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { tailwind } from "@tailwind"; import { translate } from "@translations"; import { Dispatch, useEffect, useState } from "react"; @@ -23,7 +23,7 @@ import { hasOceanTXQueued, transactionQueue, DFIUtxoSelector, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { queueConvertTransaction } from "@hooks/wallet/Conversion"; import { useAppDispatch } from "@hooks/useAppDispatch"; import { LoanSchemeOptions } from "@screens/AppNavigator/screens/Loans/components/LoanSchemeOptions"; diff --git a/mobile-app/app/screens/AppNavigator/screens/Loans/screens/EditCollateralScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Loans/screens/EditCollateralScreen.tsx index 01bab2caac..1c1b439c50 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Loans/screens/EditCollateralScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Loans/screens/EditCollateralScreen.tsx @@ -22,7 +22,7 @@ import { BottomSheetTokenList, TokenType, } from "@components/BottomSheetTokenList"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { useSelector } from "react-redux"; import { RootState } from "@store"; import { fetchCollateralTokens } from "@store/loans"; @@ -138,7 +138,7 @@ export function EditCollateralScreen({ @@ -154,7 +154,7 @@ export function EditCollateralScreen({ )} {activeVault.collateralAmounts.map((collateral, index) => { const collateralItem = collateralTokens.find( - (col) => col.token.id === collateral.id + (col) => col.token.id === collateral.id, ); if (collateralItem !== undefined) { const addOrRemoveParams = { @@ -244,7 +244,7 @@ function VaultIdSection(props: { vault: LoanVaultActive }): JSX.Element { colRatio, minColRatio, totalLoanAmount, - totalCollateralValue + totalCollateralValue, ); const colors = useCollateralizationRatioColor({ colRatio, @@ -280,7 +280,7 @@ function VaultIdSection(props: { vault: LoanVaultActive }): JSX.Element { value={getPrecisedTokenValue(vault.collateralValue ?? 0)} lhs={translate( "screens/EditCollateralScreen", - "Total collateral (USD)" + "Total collateral (USD)", )} isOraclePrice /> @@ -294,7 +294,7 @@ function VaultIdSection(props: { vault: LoanVaultActive }): JSX.Element { diff --git a/mobile-app/app/screens/AppNavigator/screens/Loans/screens/EditLoanSchemeScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Loans/screens/EditLoanSchemeScreen.tsx index 1590df552f..b859652812 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Loans/screens/EditLoanSchemeScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Loans/screens/EditLoanSchemeScreen.tsx @@ -17,11 +17,8 @@ import { NumericFormat as NumberFormat } from "react-number-format"; import { useSelector } from "react-redux"; import { RootState } from "@store"; import { ascColRatioLoanScheme } from "@store/loans"; -import { - hasTxQueued, - hasOceanTXQueued, -} from "@waveshq/walletkit-ui/dist/store"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { hasTxQueued, hasOceanTXQueued } from "@waveshq/walletkit-ui/store"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { useLogger } from "@shared-contexts/NativeLoggingProvider"; import { LoanSchemeOptions } from "@screens/AppNavigator/screens/Loans/components/LoanSchemeOptions"; import { ButtonV2 } from "@components/ButtonV2"; @@ -39,10 +36,10 @@ export function EditLoanSchemeScreen({ const { vaultId } = route.params; const { vaults } = useSelector((state: RootState) => state.loans); const loanSchemes = useSelector((state: RootState) => - ascColRatioLoanScheme(state.loans) + ascColRatioLoanScheme(state.loans), ); const hasFetchedLoanSchemes = useSelector( - (state: RootState) => state.loans.hasFetchedLoanSchemes + (state: RootState) => state.loans.hasFetchedLoanSchemes, ); const [activeVault, setActiveVault] = useState(); const [filteredLoanSchemes, setFilteredLoanSchemes] = @@ -54,10 +51,10 @@ export function EditLoanSchemeScreen({ // Continue button const hasPendingJob = useSelector((state: RootState) => - hasTxQueued(state.transactionQueue) + hasTxQueued(state.transactionQueue), ); const hasPendingBroadcastJob = useSelector((state: RootState) => - hasOceanTXQueued(state.ocean) + hasOceanTXQueued(state.ocean), ); const onSubmit = (): void => { @@ -101,15 +98,15 @@ export function EditLoanSchemeScreen({ const loanscheme: WalletLoanScheme = { disabled: new BigNumber(activeVault?.collateralRatio ?? NaN).isGreaterThan( - 0 + 0, ) && new BigNumber(activeVault?.collateralRatio ?? NaN).isLessThan( - scheme.minColRatio + scheme.minColRatio, ), ...scheme, }; return loanscheme; - }) + }), ); }, [activeVault]); @@ -155,7 +152,7 @@ export function EditLoanSchemeScreen({ > {translate( "screens/EditLoanSchemeScreen", - "Review full details in the next screen" + "Review full details in the next screen", )} )} @@ -189,7 +186,7 @@ function VaultDetail(props: { vault: LoanVaultActive }): JSX.Element { colRatio, minColRatio, totalLoanAmount, - totalCollateralValue + totalCollateralValue, ); return ( @@ -229,7 +226,7 @@ function VaultDetail(props: { vault: LoanVaultActive }): JSX.Element { "{{interestRate}}% Interest", { interestRate: vault.loanScheme.interestRate, - } + }, )} @@ -253,7 +250,7 @@ function VaultDetail(props: { vault: LoanVaultActive }): JSX.Element { { "text-red-v2": vaultState.status === VaultStatus.NearLiquidation, - } + }, )} dark={tailwind( "text-mono-dark-v2-900", @@ -269,7 +266,7 @@ function VaultDetail(props: { vault: LoanVaultActive }): JSX.Element { { "text-red-v2": vaultState.status === VaultStatus.NearLiquidation, - } + }, )} style={tailwind("text-sm font-semibold-v2")} > @@ -280,14 +277,14 @@ function VaultDetail(props: { vault: LoanVaultActive }): JSX.Element { .charAt(0) .toUpperCase()}${vaultState.status .slice(1) - .toLowerCase()}` + .toLowerCase()}`, ) : `${val}%`} )} thousandSeparator value={new BigNumber( - vault.informativeRatio === "-1" ? NaN : vault.informativeRatio + vault.informativeRatio === "-1" ? NaN : vault.informativeRatio, ).toFixed(2)} /> @@ -307,7 +304,7 @@ function VaultDetail(props: { vault: LoanVaultActive }): JSX.Element { )} thousandSeparator value={new BigNumber(vault.loanScheme.minColRatio ?? 0).toFixed( - 0 + 0, )} /> @@ -320,7 +317,7 @@ function VaultDetail(props: { vault: LoanVaultActive }): JSX.Element { > {translate( "screens/EditLoanSchemeScreen", - "You can only select a scheme lower than your vault's current collateralization." + "You can only select a scheme lower than your vault's current collateralization.", )} diff --git a/mobile-app/app/screens/AppNavigator/screens/Loans/screens/PaybackLoanScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Loans/screens/PaybackLoanScreen.tsx index 9f11afa8b8..d45a270ddd 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Loans/screens/PaybackLoanScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Loans/screens/PaybackLoanScreen.tsx @@ -22,7 +22,7 @@ import { hasTxQueued, hasOceanTXQueued, tokensSelector, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { useLoanOperations } from "@screens/AppNavigator/screens/Loans/hooks/LoanOperations"; import { getActivePrice } from "@screens/AppNavigator/screens/Auctions/helpers/ActivePrice"; import { @@ -44,7 +44,7 @@ import { TextRowV2 } from "@components/TextRowV2"; import { NumberRowV2 } from "@components/NumberRowV2"; import { SubmitButtonGroup } from "@components/SubmitButtonGroup"; import { useToast } from "react-native-toast-notifications"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { useAppDispatch } from "@hooks/useAppDispatch"; import { useLogger } from "@shared-contexts/NativeLoggingProvider"; import { getTokenAmount } from "../hooks/LoanPaymentTokenRate"; @@ -410,8 +410,8 @@ export function PaybackLoanScreen({ navigation, route }: Props): JSX.Element { routeParams.isPaybackDUSDUsingCollateral ? "Use your DUSD collaterals to fully pay off your DUSD loan." : new BigNumber(loanTokenOutstandingBal).lt(amountToPay) - ? "Any excess payment will be returned." - : "Review full details in the next screen", + ? "Any excess payment will be returned." + : "Review full details in the next screen", )} )} diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/PortfolioNavigator.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/PortfolioNavigator.tsx index 25ce959581..cf1f187147 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/PortfolioNavigator.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/PortfolioNavigator.tsx @@ -1,6 +1,6 @@ import { NavigationProp, useNavigation } from "@react-navigation/native"; import { createStackNavigator } from "@react-navigation/stack"; -import { AddressType, WalletToken } from "@waveshq/walletkit-ui/dist/store"; +import { AddressType, WalletToken } from "@waveshq/walletkit-ui/store"; import BigNumber from "bignumber.js"; import { Image } from "expo-image"; import { Platform, View } from "react-native"; diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/PortfolioScreen.test.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/PortfolioScreen.test.tsx index 3cf799fe60..c7cc221476 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/PortfolioScreen.test.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/PortfolioScreen.test.tsx @@ -2,11 +2,7 @@ import { configureStore } from "@reduxjs/toolkit"; import { fireEvent, render } from "@testing-library/react-native"; import { Provider } from "react-redux"; import { RootState } from "@store"; -import { - block, - wallet, - setTokenSymbol, -} from "@waveshq/walletkit-ui/dist/store"; +import { block, wallet, setTokenSymbol } from "@waveshq/walletkit-ui/store"; import { loans } from "@store/loans"; import { LoanVaultState } from "@defichain/whale-api-client/dist/api/loan"; import { futureSwaps } from "@store/futureSwap"; @@ -42,7 +38,7 @@ jest.mock("react-native/Libraries/Utilities/Platform", () => ({ select: () => jest.fn, })); -jest.mock("@waveshq/walletkit-ui/dist/store/website", () => ({ +jest.mock("@waveshq/walletkit-ui/store/website", () => ({ useGetAnnouncementsQuery: () => ({ data: [], isSuccess: true }), useGetStatusQuery: () => jest.fn(), })); @@ -54,7 +50,7 @@ jest.mock( return <>; } return { Announcements }; - } + }, ); describe("portfolio page", () => { diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/PortfolioScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/PortfolioScreen.tsx index 315147da0c..0c092949bf 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/PortfolioScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/PortfolioScreen.tsx @@ -27,7 +27,7 @@ import { ocean, tokensSelector, WalletToken, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { tailwind } from "@tailwind"; import BigNumber from "bignumber.js"; import React, { diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/ActionButtons.test.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/ActionButtons.test.tsx index 1b39090a95..fe9458d97a 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/ActionButtons.test.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/ActionButtons.test.tsx @@ -2,7 +2,7 @@ import { render } from "@testing-library/react-native"; import { Provider } from "react-redux"; import { configureStore } from "@reduxjs/toolkit"; import { RootState } from "@store"; -import { setTokenSymbol, wallet } from "@waveshq/walletkit-ui/dist/store"; +import { setTokenSymbol, wallet } from "@waveshq/walletkit-ui/store"; import { futureSwaps } from "@store/futureSwap"; import { StoreProvider } from "@contexts/StoreProvider"; import { ActionButtons } from "./ActionButtons"; diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/ActionButtons.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/ActionButtons.tsx index 9822d8a55d..78227b2d95 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/ActionButtons.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/ActionButtons.tsx @@ -5,10 +5,7 @@ import { ThemedTextV2, ThemedTouchableOpacityV2, } from "@components/themed"; -import { - DFITokenSelector, - DFIUtxoSelector, -} from "@waveshq/walletkit-ui/dist/store"; +import { DFITokenSelector, DFIUtxoSelector } from "@waveshq/walletkit-ui/store"; import { useFeatureFlagContext } from "@contexts/FeatureFlagContext"; import { NavigationProp, useNavigation } from "@react-navigation/native"; import { RootState } from "@store"; diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/AddressControlScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/AddressControlScreen.tsx index 4e83c73581..224251decc 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/AddressControlScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/AddressControlScreen.tsx @@ -28,7 +28,7 @@ import { hasTxQueued, hasOceanTXQueued, wallet as walletReducer, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { loans } from "@store/loans"; import { useAppDispatch } from "@hooks/useAppDispatch"; import { PortfolioParamList } from "../PortfolioNavigator"; @@ -47,7 +47,7 @@ export function AddressControlScreen(): JSX.Element { testID="switch_address_screen_title" text={translate( "screens/AddressControlScreen", - "Switch to another address" + "Switch to another address", )} /> navigation.goBack()} /> @@ -69,7 +69,7 @@ export function AddressControlModal({ > @@ -80,7 +80,7 @@ export function AddressControlModal({ > {translate( "screens/AddressControlScreen", - "Switch to another address" + "Switch to another address", )} @@ -202,7 +202,7 @@ export function AddressControlCard({ > {translate( "screens/AddressControlScreen", - "CREATE WALLET ADDRESS" + "CREATE WALLET ADDRESS", )} @@ -225,10 +225,10 @@ export function AddressItemRow({ onPress: () => void; }): JSX.Element { const hasPendingJob = useSelector((state: RootState) => - hasTxQueued(state.transactionQueue) + hasTxQueued(state.transactionQueue), ); const hasPendingBroadcastJob = useSelector((state: RootState) => - hasOceanTXQueued(state.ocean) + hasOceanTXQueued(state.ocean), ); return ( diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/AddressRow.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/AddressRow.tsx index 0575e904b3..6bfbede165 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/AddressRow.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/AddressRow.tsx @@ -1,7 +1,7 @@ import { View } from "react-native"; import { tailwind } from "@tailwind"; import { translate } from "@translations"; -import { AddressType } from "@waveshq/walletkit-ui/dist/store"; +import { AddressType } from "@waveshq/walletkit-ui/store"; import { ThemedIcon, ThemedTextV2, diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/Announcements.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/Announcements.tsx index ec18d30243..99cc0d577a 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/Announcements.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/Announcements.tsx @@ -8,7 +8,7 @@ import { ThemedViewV2, } from "@components/themed"; import { tailwind } from "@tailwind"; -import { useGetAnnouncementsQuery } from "@waveshq/walletkit-ui/dist/store"; +import { useGetAnnouncementsQuery } from "@waveshq/walletkit-ui/store"; import { AnnouncementData } from "@waveshq/walletkit-core"; import { satisfies } from "semver"; import { useLanguageContext } from "@shared-contexts/LanguageProvider"; @@ -70,25 +70,25 @@ export function Announcements(): JSX.Element { "0.0.0", language, hiddenAnnouncements, - emergencyMsgContent + emergencyMsgContent, ); const blockchainIsDownAnnouncement = findDisplayedAnnouncementForVersion( "0.0.0", language, hiddenAnnouncements, - blockchainStatusAnnouncement + blockchainStatusAnnouncement, ); const oceanIsDownAnnouncement = findDisplayedAnnouncementForVersion( "0.0.0", language, hiddenAnnouncements, - oceanStatusAnnouncement + oceanStatusAnnouncement, ); const announcement = findDisplayedAnnouncementForVersion( nativeApplicationVersion ?? "0.0.0", language, hiddenAnnouncements, - announcements + announcements, ); /* @@ -265,7 +265,7 @@ export function AnnouncementBannerV2({ "border-mono-dark-v2-900": isOtherAnnouncement && !isLight, "border-orange-v2": announcement.type === "OUTAGE", "border-red-v2": announcement.type === "EMERGENCY", - } + }, ), containerStyle?.style, ]} @@ -364,7 +364,7 @@ export function findDisplayedAnnouncementForVersion( version: string, language: string, hiddenAnnouncements: string[], - announcements?: AnnouncementData[] + announcements?: AnnouncementData[], ): Announcement | undefined { if (announcements === undefined || announcements.length === 0) { return; @@ -393,7 +393,7 @@ export function findDisplayedAnnouncementForVersion( function getDisplayAnnouncement( hiddenAnnouncements: string[], - announcement: AnnouncementData + announcement: AnnouncementData, ): boolean { if (announcement === undefined) { return false; diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/BottomSheetAddressDetailV2.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/BottomSheetAddressDetailV2.tsx index 334577215e..fc7c6e2aea 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/BottomSheetAddressDetailV2.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/BottomSheetAddressDetailV2.tsx @@ -25,7 +25,7 @@ import { hasOceanTXQueued, hasTxQueued, wallet as walletReducer, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { useSelector } from "react-redux"; import { loans } from "@store/loans"; import { RootState } from "@store"; diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/CreateOrEditAddressLabelForm.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/CreateOrEditAddressLabelForm.tsx index 12cda08eff..b96b4226da 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/CreateOrEditAddressLabelForm.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/CreateOrEditAddressLabelForm.tsx @@ -22,7 +22,7 @@ import { DomainType, useDomainContext } from "@contexts/DomainContext"; import { useWalletContext } from "@shared-contexts/WalletContext"; import { useAppDispatch } from "@hooks/useAppDispatch"; import { WhaleWalletAccount } from "@defichain/whale-api-wallet"; -import { transactionQueue } from "@waveshq/walletkit-ui/dist/store"; +import { transactionQueue } from "@waveshq/walletkit-ui/store"; import { CTransactionSegWit } from "@defichain/jellyfish-transaction/dist"; import { ButtonV2 } from "@components/ButtonV2"; import { debounce } from "lodash"; diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/DFIBalanceCard.test.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/DFIBalanceCard.test.tsx index 5c5f11e026..41cbbc9a8b 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/DFIBalanceCard.test.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/DFIBalanceCard.test.tsx @@ -1,9 +1,9 @@ import { render } from "@testing-library/react-native"; import { RootState } from "@store"; -import { setTokenSymbol, wallet } from "@waveshq/walletkit-ui/dist/store"; +import { setTokenSymbol, wallet } from "@waveshq/walletkit-ui/store"; import { Provider } from "react-redux"; import { configureStore } from "@reduxjs/toolkit"; -import { block } from "@waveshq/walletkit-ui/dist/store/block"; +import { block } from "@waveshq/walletkit-ui/store/block"; import { loans } from "@store/loans"; import { LoanVaultState } from "@defichain/whale-api-client/dist/api/loan"; import { evm } from "@store/evm"; diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/DFIBalanceCard.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/DFIBalanceCard.tsx index 01c18cdd3e..88b920fa75 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/DFIBalanceCard.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/DFIBalanceCard.tsx @@ -4,7 +4,7 @@ import { DFITokenSelector, DFIUtxoSelector, unifiedDFISelector, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { tailwind } from "@tailwind"; import { TouchableOpacity, Text, View, Platform } from "react-native"; import { LinearGradient } from "expo-linear-gradient"; diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/TokenBreakdownDetails.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/TokenBreakdownDetails.tsx index b6dbeb81e4..4b4065f7c5 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/TokenBreakdownDetails.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/TokenBreakdownDetails.tsx @@ -1,7 +1,7 @@ import { View } from "@components"; import { TextSkeletonLoader } from "@components/TextSkeletonLoader"; import { ThemedProps, ThemedText } from "@components/themed"; -import { WalletToken } from "@waveshq/walletkit-ui/dist/store"; +import { WalletToken } from "@waveshq/walletkit-ui/store"; import { tailwind } from "@tailwind"; import { translate } from "@translations"; import BigNumber from "bignumber.js"; diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/TokenBreakdownDetailsV2.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/TokenBreakdownDetailsV2.tsx index a0e9c681fc..2bd5738fe6 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/TokenBreakdownDetailsV2.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/TokenBreakdownDetailsV2.tsx @@ -4,7 +4,7 @@ import { ThemedProps, ThemedTextV2, ThemedViewV2 } from "@components/themed"; import { AddressToken } from "@defichain/whale-api-client/dist/api/address"; import { PoolPairData } from "@defichain/whale-api-client/dist/api/poolpairs"; import { RootState } from "@store"; -import { WalletToken } from "@waveshq/walletkit-ui/dist/store"; +import { WalletToken } from "@waveshq/walletkit-ui/store"; import { tailwind } from "@tailwind"; import { translate } from "@translations"; import BigNumber from "bignumber.js"; diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/TotalPortfolio.test.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/TotalPortfolio.test.tsx index b3c2b5b11d..2679f2dcdd 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/TotalPortfolio.test.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/components/TotalPortfolio.test.tsx @@ -1,9 +1,9 @@ import { render } from "@testing-library/react-native"; import { RootState } from "@store"; -import { setTokenSymbol, wallet } from "@waveshq/walletkit-ui/dist/store"; +import { setTokenSymbol, wallet } from "@waveshq/walletkit-ui/store"; import { Provider } from "react-redux"; import { configureStore } from "@reduxjs/toolkit"; -import { block } from "@waveshq/walletkit-ui/dist/store/block"; +import { block } from "@waveshq/walletkit-ui/store/block"; import BigNumber from "bignumber.js"; import { loans } from "@store/loans"; import { PortfolioButtonGroupTabKey, TotalPortfolio } from "./TotalPortfolio"; diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/hooks/TokenBalance.ts b/mobile-app/app/screens/AppNavigator/screens/Portfolio/hooks/TokenBalance.ts index 1a6b7e5db8..3fd9a601bb 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/hooks/TokenBalance.ts +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/hooks/TokenBalance.ts @@ -1,7 +1,7 @@ import { useSelector } from "react-redux"; import BigNumber from "bignumber.js"; import { RootState } from "@store"; -import { WalletToken, tokensSelector } from "@waveshq/walletkit-ui/dist/store"; +import { WalletToken, tokensSelector } from "@waveshq/walletkit-ui/store"; import { useMemo } from "react"; import { DomainType } from "@contexts/DomainContext"; import { useEvmTokenBalances } from "./EvmTokenBalances"; @@ -70,8 +70,8 @@ export function useTokenBalance(): { token.id === "0" ? "DFI" : token.id === "0_utxo" - ? "UTXO" - : token.displaySymbol, + ? "UTXO" + : token.displaySymbol, symbol: token.symbol, isLPS: false, domainType: DomainType.DVM, diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/hooks/TokenBestPath.test.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/hooks/TokenBestPath.test.tsx index e23eb94a47..cd0b7ea62a 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/hooks/TokenBestPath.test.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/hooks/TokenBestPath.test.tsx @@ -3,7 +3,7 @@ import { Provider } from "react-redux"; import { configureStore } from "@reduxjs/toolkit"; import { renderHook } from "@testing-library/react-native"; import BigNumber from "bignumber.js"; -import { block, DexItem, wallet } from "@waveshq/walletkit-ui/dist/store"; +import { block, DexItem, wallet } from "@waveshq/walletkit-ui/store"; import { useTokenBestPath } from "./TokenBestPath"; jest.mock("@react-navigation/native", () => ({ @@ -231,7 +231,7 @@ describe("Token Best Path - Get Best Path (DEX)", () => { const priceA = await result.current.calculatePriceRates( "1", "3", - new BigNumber("2") + new BigNumber("2"), ); // Swap through BTC to USDT through BTC -> DFI -> USDT @@ -246,7 +246,7 @@ describe("Token Best Path - Get Best Path (DEX)", () => { const priceB = await result.current.calculatePriceRates( "3", "1", - new BigNumber("1") + new BigNumber("1"), ); expect(priceB).toStrictEqual({ aToBPrice: new BigNumber("0.0001"), diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/hooks/TokenBestPath.ts b/mobile-app/app/screens/AppNavigator/screens/Portfolio/hooks/TokenBestPath.ts index 4f3929916c..56b95a7087 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/hooks/TokenBestPath.ts +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/hooks/TokenBestPath.ts @@ -8,7 +8,7 @@ import { import { useSelector } from "react-redux"; import { CacheApi } from "@api/cache"; import { useNetworkContext } from "@waveshq/walletkit-ui"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; interface CalculatePriceRatesProps { aToBPrice: BigNumber; @@ -21,15 +21,15 @@ interface TokenBestPath { calculatePriceRates: ( fromTokenId: string, toTokenId: string, - amount: BigNumber + amount: BigNumber, ) => Promise; getArbitraryPoolPair: ( tokenAId: string, - tokenBId: string + tokenBId: string, ) => Promise; getBestPath: ( fromTokenId: string, - toTokenId: string + toTokenId: string, ) => Promise; } @@ -47,27 +47,27 @@ export function useTokenBestPath(): TokenBestPath { async (tokenAId: string, tokenBId: string): Promise => { const { bestPath } = await getBestPath( getTokenId(tokenAId), - getTokenId(tokenBId) + getTokenId(tokenBId), ); return bestPath.reduce( (poolPairs: PoolPairData[], path: { poolPairId: string }) => { const pair = pairs.find( - (eachPair) => eachPair.data.id === path.poolPairId + (eachPair) => eachPair.data.id === path.poolPairId, ); if (pair === undefined) { return poolPairs; } return [...poolPairs, pair.data]; }, - [] + [], ); }, - [pairs, blockCount] + [pairs, blockCount], ); const getBestPath = async ( fromTokenId: string, - toTokenId: string + toTokenId: string, ): Promise => { const key = `WALLET.${network}.${ blockCount ?? 0 @@ -78,7 +78,7 @@ export function useTokenBestPath(): TokenBestPath { } const bestPathData = await client.poolpairs.getBestPath( fromTokenId, - toTokenId + toTokenId, ); CacheApi.set(key, bestPathData); return bestPathData; @@ -88,30 +88,30 @@ export function useTokenBestPath(): TokenBestPath { async ( fromTokenId: string, toTokenId: string, - amount: BigNumber + amount: BigNumber, ): Promise => { const bestPathDataFromTokenAtoB = await getBestPath( getTokenId(fromTokenId), - getTokenId(toTokenId) + getTokenId(toTokenId), ); const bestPathDataFromTokenBtoA = await getBestPath( getTokenId(toTokenId), - getTokenId(fromTokenId) + getTokenId(fromTokenId), ); return { aToBPrice: new BigNumber(bestPathDataFromTokenAtoB.estimatedReturn), bToAPrice: new BigNumber(bestPathDataFromTokenBtoA.estimatedReturn), estimated: new BigNumber( - bestPathDataFromTokenAtoB.estimatedReturn + bestPathDataFromTokenAtoB.estimatedReturn, ).times(amount), estimatedLessDexFees: new BigNumber( - bestPathDataFromTokenAtoB.estimatedReturnLessDexFees + bestPathDataFromTokenAtoB.estimatedReturnLessDexFees, ).times(amount), }; }, - [pairs, blockCount] + [pairs, blockCount], ); return { diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/hooks/TokenLockedBalance.ts b/mobile-app/app/screens/AppNavigator/screens/Portfolio/hooks/TokenLockedBalance.ts index 70a7d1dc55..006585168b 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/hooks/TokenLockedBalance.ts +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/hooks/TokenLockedBalance.ts @@ -1,7 +1,7 @@ import { LoanVaultState } from "@defichain/whale-api-client/dist/api/loan"; import { RootState } from "@store"; import { vaultsSelector } from "@store/loans"; -import { dexPricesSelectorByDenomination } from "@waveshq/walletkit-ui/dist/store"; +import { dexPricesSelectorByDenomination } from "@waveshq/walletkit-ui/store"; import BigNumber from "bignumber.js"; import { clone } from "lodash"; import { useCallback, useEffect, useState } from "react"; @@ -31,7 +31,7 @@ export function useTokenLockedBalance({ useState>(); const { getTokenPrice } = useTokenPrice(denominationCurrency); const prices = useSelector((state: RootState) => - dexPricesSelectorByDenomination(state.wallet, denominationCurrency) + dexPricesSelectorByDenomination(state.wallet, denominationCurrency), ); useEffect(() => { @@ -54,7 +54,7 @@ export function useTokenLockedBalance({ }; const tokenValue = getTokenPrice( collateral.symbol, - new BigNumber(collateral.amount) + new BigNumber(collateral.amount), ); lockedBalance.set(collateral.displaySymbol, { amount: token.amount.plus(collateral.amount), diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/hooks/TokenPrice.test.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/hooks/TokenPrice.test.tsx index f4d7a63383..f4ba4ca434 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/hooks/TokenPrice.test.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/hooks/TokenPrice.test.tsx @@ -3,8 +3,8 @@ import { Provider } from "react-redux"; import { configureStore } from "@reduxjs/toolkit"; import { renderHook } from "@testing-library/react-native"; import BigNumber from "bignumber.js"; -import { DexItem, wallet } from "@waveshq/walletkit-ui/dist/store"; -import { block } from "@waveshq/walletkit-ui/dist/store/block"; +import { DexItem, wallet } from "@waveshq/walletkit-ui/store"; +import { block } from "@waveshq/walletkit-ui/store/block"; import { useTokenPrice } from "./TokenPrice"; jest.mock("@react-navigation/native", () => ({ @@ -258,13 +258,13 @@ describe("Token Price - Get Token Price (DEX)", () => { it("should be able to get the token price", () => { const { result } = renderHook(() => useTokenPrice(), { wrapper }); expect( - result.current.getTokenPrice("BTC", new BigNumber("1"), false) + result.current.getTokenPrice("BTC", new BigNumber("1"), false), ).toStrictEqual(new BigNumber("10000")); expect( - result.current.getTokenPrice("ETH", new BigNumber("1"), false) + result.current.getTokenPrice("ETH", new BigNumber("1"), false), ).toStrictEqual(new BigNumber("100")); expect( - result.current.getTokenPrice("USDT", new BigNumber("12"), false) + result.current.getTokenPrice("USDT", new BigNumber("12"), false), ).toStrictEqual(new BigNumber("12")); }); @@ -280,7 +280,7 @@ describe("Token Price - Get Token Price (DEX)", () => { const usdTokenA = tokenAAmount.times(10000); // USDT price for tokenA const usdTokenB = tokenBAmount.times(10000); // USDT price for tokenB expect( - result.current.getTokenPrice("BTC-DFI", new BigNumber("1"), true) + result.current.getTokenPrice("BTC-DFI", new BigNumber("1"), true), ).toStrictEqual(usdTokenA.plus(usdTokenB)); }); }); diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/hooks/TokenPrice.ts b/mobile-app/app/screens/AppNavigator/screens/Portfolio/hooks/TokenPrice.ts index 6dde66d025..485dc1ac69 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/hooks/TokenPrice.ts +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/hooks/TokenPrice.ts @@ -2,20 +2,20 @@ import { useCallback } from "react"; import BigNumber from "bignumber.js"; import { RootState } from "@store"; import { useSelector } from "react-redux"; -import { dexPricesSelectorByDenomination } from "@waveshq/walletkit-ui/dist/store"; +import { dexPricesSelectorByDenomination } from "@waveshq/walletkit-ui/store"; interface TokenPrice { getTokenPrice: ( symbol: string, amount: BigNumber, - isLPS?: boolean + isLPS?: boolean, ) => BigNumber; } export function useTokenPrice(denominationTokenSymbol = "USDT"): TokenPrice { const blockCount = useSelector((state: RootState) => state.block.count); const prices = useSelector((state: RootState) => - dexPricesSelectorByDenomination(state.wallet, denominationTokenSymbol) + dexPricesSelectorByDenomination(state.wallet, denominationTokenSymbol), ); const pairs = useSelector((state: RootState) => state.wallet.poolpairs); @@ -39,7 +39,7 @@ export function useTokenPrice(denominationTokenSymbol = "USDT"): TokenPrice { return new BigNumber(""); } const ratioToTotal = new BigNumber(amount).div( - pair.data.totalLiquidity.token + pair.data.totalLiquidity.token, ); const tokenAAmount = ratioToTotal .times(pair.data.tokenA.reserve) @@ -52,10 +52,10 @@ export function useTokenPrice(denominationTokenSymbol = "USDT"): TokenPrice { return usdTokenA.plus(usdTokenB); } return new BigNumber(prices[symbol]?.denominationPrice ?? 0).multipliedBy( - amount + amount, ); }, - [prices, pairs, blockCount] + [prices, pairs, blockCount], ); return { diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/ConfirmWithdrawFutureSwapScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/ConfirmWithdrawFutureSwapScreen.tsx index 41ab267176..d0a3d194d5 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/ConfirmWithdrawFutureSwapScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/ConfirmWithdrawFutureSwapScreen.tsx @@ -10,7 +10,7 @@ import { hasOceanTXQueued, transactionQueue, AddressType, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { StackScreenProps } from "@react-navigation/stack"; import { NativeLoggingProps, @@ -44,10 +44,10 @@ export function ConfirmWithdrawFutureSwapScreen({ const addressLabel = useAddressLabel(address); const { getTokenPrice } = useTokenPrice(); const hasPendingJob = useSelector((state: RootState) => - hasTxQueued(state.transactionQueue) + hasTxQueued(state.transactionQueue), ); const hasPendingBroadcastJob = useSelector((state: RootState) => - hasOceanTXQueued(state.ocean) + hasOceanTXQueued(state.ocean), ); const blockCount = useSelector((state: RootState) => state.block.count ?? 0); const { isEnded } = useFutureSwapDate(executionBlock, blockCount); @@ -75,7 +75,7 @@ export function ConfirmWithdrawFutureSwapScreen({ () => { onTransactionBroadcast(isOnPage, navigation.dispatch); }, - logger + logger, ); } @@ -95,7 +95,7 @@ export function ConfirmWithdrawFutureSwapScreen({ , onBroadcast: () => void, - logger: NativeLoggingProps + logger: NativeLoggingProps, ): Promise { try { const signer = async ( - account: WhaleWalletAccount + account: WhaleWalletAccount, ): Promise => { const script = await account.getScript(); const builder = account.withTransactionBuilder(); @@ -208,7 +208,7 @@ async function withdrawFutureSwap( destination: source.isLoanToken ? 0 : Number(destination.tokenId), withdraw: true, }, - script + script, ); return new CTransactionSegWit(signed); }; @@ -225,12 +225,12 @@ async function withdrawFutureSwap( amountToWithdraw: amountToWithdraw, sourceSymbol: sourceSymbol, destinationSymbol: destination.displaySymbol, - } + }, ), drawerMessages: { preparing: translate( "screens/OceanInterface", - "Preparing withdrawal…" + "Preparing withdrawal…", ), waiting: translate( "screens/OceanInterface", @@ -238,12 +238,12 @@ async function withdrawFutureSwap( { amountToWithdraw: amountToWithdraw, sourceSymbol: sourceSymbol, - } + }, ), complete: translate("screens/OceanInterface", "Withdrawal completed"), }, onBroadcast, - }) + }), ); } catch (e) { logger.error(e); diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/ConvertConfirmationScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/ConvertConfirmationScreen.tsx index c5e8278818..f738f1ee95 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/ConvertConfirmationScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/ConvertConfirmationScreen.tsx @@ -10,7 +10,7 @@ import { hasTxQueued, hasOceanTXQueued, transactionQueue, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { tailwind } from "@tailwind"; import { translate } from "@translations"; import { diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/ConvertScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/ConvertScreen.tsx index c1b1c8bd4e..36a1273b65 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/ConvertScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/ConvertScreen.tsx @@ -13,13 +13,13 @@ import { ThemedTouchableOpacityV2, ThemedViewV2, } from "@components/themed"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { RootState } from "@store"; import { hasOceanTXQueued, hasTxQueued, tokensSelector, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { getColor, tailwind } from "@tailwind"; import { translate } from "@translations"; import { useLogger } from "@shared-contexts/NativeLoggingProvider"; @@ -480,8 +480,8 @@ export function ConvertScreen(props: Props): JSX.Element { inlineTextStatus === InlineTextStatus.Error ? "Insufficient balance" : inlineTextStatus === InlineTextStatus.Warning - ? "A small amount of UTXO is reserved for fees" - : "", + ? "A small amount of UTXO is reserved for fees" + : "", { amount: new BigNumber(sourceToken.available).toFixed(8), unit: sourceToken.token.displaySymbol, diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/FutureSwapScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/FutureSwapScreen.tsx index 823e7c2599..56f345d622 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/FutureSwapScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/FutureSwapScreen.tsx @@ -23,7 +23,7 @@ import { fetchLoanTokens } from "@store/loans"; import { useWhaleApiClient, useWhaleRpcClient, -} from "@waveshq/walletkit-ui/dist/contexts"; +} from "@waveshq/walletkit-ui/contexts"; import { useDeFiScanContext } from "@shared-contexts/DeFiScanContext"; import { useAppDispatch } from "@hooks/useAppDispatch"; import { openURL } from "@api/linking"; @@ -41,15 +41,15 @@ export function FutureSwapScreen({ navigation }: Props): JSX.Element { const whaleApiClient = useWhaleApiClient(); const { address } = useWalletContext(); const futureSwaps = useSelector((state: RootState) => - futureSwapSelector(state) + futureSwapSelector(state), ); const blockCount = useSelector((state: RootState) => state.block.count ?? 0); const executionBlock = useSelector( - (state: RootState) => state.futureSwaps.executionBlock + (state: RootState) => state.futureSwaps.executionBlock, ); const { timeRemaining, transactionDate, isEnded } = useFutureSwapDate( executionBlock, - blockCount + blockCount, ); useEffect(() => { @@ -64,7 +64,7 @@ export function FutureSwapScreen({ navigation }: Props): JSX.Element { fetchFutureSwaps({ client: whaleRpcClient, address, - }) + }), ); dispatch(fetchExecutionBlock({ client: whaleRpcClient })); }); @@ -88,7 +88,7 @@ export function FutureSwapScreen({ navigation }: Props): JSX.Element { return ( ); }, - [isEnded, transactionDate] + [isEnded, transactionDate], ); return ( @@ -198,7 +198,7 @@ function ExecutionBlockInfo({ > {`${translate( "screens/FutureSwapScreen", - "Target block" + "Target block", )}: ${value}`} )} @@ -212,7 +212,7 @@ function ExecutionBlockInfo({ {`${transactionDate} (${translate( "screens/FutureSwapScreen", "{{time}} left", - { time: timeRemaining.trim() } + { time: timeRemaining.trim() }, )})`} {translate( "screens/FutureSwapScreen", - "Amount will be refunded automatically if transaction(s) failed" + "Amount will be refunded automatically if transaction(s) failed", )} diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/GetDFIScreen.test.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/GetDFIScreen.test.tsx index 35b5db7aa6..9298e3c7d6 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/GetDFIScreen.test.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/GetDFIScreen.test.tsx @@ -3,8 +3,8 @@ import { fireEvent, render } from "@testing-library/react-native"; import * as Clipboard from "expo-clipboard"; import { Provider } from "react-redux"; import { RootState } from "@store"; -import { wallet } from "@waveshq/walletkit-ui/dist/store"; -import { block } from "@waveshq/walletkit-ui/dist/store/block"; +import { wallet } from "@waveshq/walletkit-ui/store"; +import { block } from "@waveshq/walletkit-ui/store/block"; import { GetDFIScreen } from "./GetDFIScreen"; jest.mock("@shared-contexts/WalletContext"); @@ -15,7 +15,7 @@ jest.mock("expo-clipboard", () => ({ setStringAsync: jest.fn(), })); -jest.mock("@waveshq/walletkit-ui/dist/contexts", () => ({ +jest.mock("@waveshq/walletkit-ui/contexts", () => ({ useWhaleApiClient: () => ({ prices: { get: async () => ({ diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/GetDFIScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/GetDFIScreen.tsx index 9571e2f3d7..68461e3863 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/GetDFIScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/GetDFIScreen.tsx @@ -26,7 +26,7 @@ import { NumericFormat as NumberFormat } from "react-number-format"; import BigNumber from "bignumber.js"; import { useSelector } from "react-redux"; import { RootState } from "@store"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { PortfolioParamList } from "@screens/AppNavigator/screens/Portfolio/PortfolioNavigator"; import { ConvertIcon } from "@components/icons/assets/ConvertIcon"; import { DomainType, useDomainContext } from "@contexts/DomainContext"; diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/OCG/CFPDetailScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/OCG/CFPDetailScreen.tsx index fa5df3627d..231e76970e 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/OCG/CFPDetailScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/OCG/CFPDetailScreen.tsx @@ -26,10 +26,10 @@ import { DFIUtxoSelector, hasOceanTXQueued, hasTxQueued, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { useLogger } from "@shared-contexts/NativeLoggingProvider"; import { useAppDispatch } from "@hooks/useAppDispatch"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { OCGProposalType } from "@screens/AppNavigator/screens/Portfolio/screens/OCG/OCGProposalsScreen"; import { AddressRow } from "@screens/AppNavigator/screens/Portfolio/components/AddressRow"; import { ButtonGroupTabKey } from "@screens/AppNavigator/screens/Portfolio/screens/AddressBookScreen"; diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/OCG/DFIPDetailScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/OCG/DFIPDetailScreen.tsx index 94b0e6a50a..1324cceb96 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/OCG/DFIPDetailScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/OCG/DFIPDetailScreen.tsx @@ -21,10 +21,10 @@ import { DFIUtxoSelector, hasOceanTXQueued, hasTxQueued, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { useAppDispatch } from "@hooks/useAppDispatch"; import { useLogger } from "@shared-contexts/NativeLoggingProvider"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { EnvironmentNetwork } from "@waveshq/walletkit-core"; import { OCGProposalType } from "@screens/AppNavigator/screens/Portfolio/screens/OCG/OCGProposalsScreen"; import { ConvertDirection } from "@screens/enum"; diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/OCG/OCGConfirmScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/OCG/OCGConfirmScreen.tsx index d6494736d0..c8fc916819 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/OCG/OCGConfirmScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/OCG/OCGConfirmScreen.tsx @@ -23,7 +23,7 @@ import { hasOceanTXQueued, hasTxQueued, transactionQueue, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { WalletAlert } from "@components/WalletAlert"; import { ScreenName } from "@screens/enum"; import { NavigationProp, useNavigation } from "@react-navigation/native"; @@ -66,10 +66,10 @@ export function OCGConfirmScreen({ route }: Props): JSX.Element { const dispatch = useAppDispatch(); const hasPendingJob = useSelector((state: RootState) => - hasTxQueued(state.transactionQueue) + hasTxQueued(state.transactionQueue), ); const hasPendingBroadcastJob = useSelector((state: RootState) => - hasOceanTXQueued(state.ocean) + hasOceanTXQueued(state.ocean), ); const [isOnPage, setIsOnPage] = useState(true); @@ -105,7 +105,7 @@ export function OCGConfirmScreen({ route }: Props): JSX.Element { () => { onTransactionBroadcast(isOnPage, navigation.dispatch); }, - logger + logger, ); setIsSubmitting(false); } @@ -119,7 +119,7 @@ export function OCGConfirmScreen({ route }: Props): JSX.Element { title: translate("screens/Settings", "Cancel transaction"), message: translate( "screens/Settings", - "By cancelling, you will lose any changes you made for your transaction." + "By cancelling, you will lose any changes you made for your transaction.", ), buttons: [ { @@ -352,7 +352,7 @@ function FeeSection({ title: translate("screens/OCGConfirmScreen", "Proposal Fees"), message: translate( "screens/OCGConfirmScreen", - "Proposals fees are implemented to encourage more responsible submissions.\nProposal fees are calculated based on the type of proposal selected, and the requested amount (only for CFP).\nRefer to our FAQ section for more detailed breakdown." + "Proposals fees are implemented to encourage more responsible submissions.\nProposal fees are calculated based on the type of proposal selected, and the requested amount (only for CFP).\nRefer to our FAQ section for more detailed breakdown.", ), iconStyle: { light: tailwind("text-mono-light-v2-500"), @@ -411,7 +411,7 @@ function AcknowledgeSwitch({ > {translate( "screens/OCGConfirmScreen", - "I acknowledge all proposal details to be correct and final. Once submitted, the proposal is no longer editable. View your posted proposal in DeFiScan." + "I acknowledge all proposal details to be correct and final. Once submitted, the proposal is no longer editable. View your posted proposal in DeFiScan.", )} @@ -446,11 +446,11 @@ async function constructSignedProposalAndSend( form: ProposalForm, dispatch: Dispatch, onBroadcast: () => void, - logger: NativeLoggingProps + logger: NativeLoggingProps, ) { try { const signer = async ( - account: WhaleWalletAccount + account: WhaleWalletAccount, ): Promise => { const script = await account.getScript(); const builder = account.withTransactionBuilder(); @@ -459,7 +459,7 @@ async function constructSignedProposalAndSend( const cfpForm = form as CFPProposalForm; const to = DeFiAddress.from( cfpForm.networkName, - cfpForm.receivingAddress + cfpForm.receivingAddress, ).getScript(); const cfp: CreateCfp = { type: 0x01, @@ -498,13 +498,13 @@ async function constructSignedProposalAndSend( drawerMessages: { preparing: translate( "screens/OCGConfirmScreen", - "Submitting proposal" + "Submitting proposal", ), waiting: translate("screens/OCGConfirmScreen", "Submitting proposal"), complete: translate("screens/OCGConfirmScreen", "Proposal Submitted"), }, onBroadcast, - }) + }), ); } catch (e) { logger.error(e); diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/ReceiveScreen.test.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/ReceiveScreen.test.tsx index 9993cc1982..1ca20f92d5 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/ReceiveScreen.test.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/ReceiveScreen.test.tsx @@ -3,7 +3,7 @@ import { fireEvent, render } from "@testing-library/react-native"; import * as Clipboard from "expo-clipboard"; import { Provider } from "react-redux"; import { RootState } from "@store"; -import { wallet } from "@waveshq/walletkit-ui/dist/store"; +import { wallet } from "@waveshq/walletkit-ui/store"; import { ReceiveScreen } from "./ReceiveScreen"; jest.mock("@shared-contexts/WalletContext"); diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/SendConfirmationScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/SendConfirmationScreen.tsx index e2ecddfc61..4c05fbc327 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/SendConfirmationScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/SendConfirmationScreen.tsx @@ -28,7 +28,7 @@ import { hasTxQueued, hasOceanTXQueued, transactionQueue, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { useAppDispatch } from "@hooks/useAppDispatch"; import { useAddressLabel } from "@hooks/useAddressLabel"; import { View } from "@components"; diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/SendScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/SendScreen.tsx index 656365e1d7..77b83783d9 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/SendScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/SendScreen.tsx @@ -8,7 +8,7 @@ import { StackScreenProps } from "@react-navigation/stack"; import { getColor, tailwind } from "@tailwind"; import { translate } from "@translations"; import { useNetworkContext, useThemeContext } from "@waveshq/walletkit-ui"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { useLogger } from "@shared-contexts/NativeLoggingProvider"; import { RootState } from "@store"; import { @@ -19,7 +19,7 @@ import { hasTxQueued, tokensSelector, WalletToken, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { LocalAddress, WhitelistedAddress } from "@store/userPreferences"; import { useDisplayUtxoWarning } from "@hooks/wallet/DisplayUtxoWarning"; import { diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/TokenDetailScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/TokenDetailScreen.tsx index cb75afd6fe..7dadabe47b 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/TokenDetailScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/TokenDetailScreen.tsx @@ -12,7 +12,7 @@ import { tokensSelector, unifiedDFISelector, WalletToken, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { getMetaScanTokenUrl, useDeFiScanContext, diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/TokenSelectionScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/TokenSelectionScreen.tsx index 88348dfcdd..01b9f4f0ef 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/TokenSelectionScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/TokenSelectionScreen.tsx @@ -12,7 +12,7 @@ import { DFITokenSelector, tokensSelector, WalletToken, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { useDebounce } from "@hooks/useDebounce"; import { useThemeContext } from "@waveshq/walletkit-ui"; import { useTokenPrice } from "@screens/AppNavigator/screens/Portfolio/hooks/TokenPrice"; diff --git a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/WithdrawFutureSwapScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/WithdrawFutureSwapScreen.tsx index 8c4f9904de..3c23ed15ae 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/WithdrawFutureSwapScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Portfolio/screens/WithdrawFutureSwapScreen.tsx @@ -12,12 +12,9 @@ import { ThemedTouchableOpacityV2, ThemedViewV2, } from "@components/themed"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { useLogger } from "@shared-contexts/NativeLoggingProvider"; -import { - hasTxQueued, - hasOceanTXQueued, -} from "@waveshq/walletkit-ui/dist/store"; +import { hasTxQueued, hasOceanTXQueued } from "@waveshq/walletkit-ui/store"; import { RootState } from "@store"; import { useSelector } from "react-redux"; import { NavigationProp, useNavigation } from "@react-navigation/native"; @@ -57,15 +54,15 @@ export function WithdrawFutureSwapScreen(props: Props): JSX.Element { const { isLight } = useThemeContext(); const { getTokenPrice } = useTokenPrice(); const hasPendingJob = useSelector((state: RootState) => - hasTxQueued(state.transactionQueue) + hasTxQueued(state.transactionQueue), ); const hasPendingBroadcastJob = useSelector((state: RootState) => - hasOceanTXQueued(state.ocean) + hasOceanTXQueued(state.ocean), ); const blockCount = useSelector((state: RootState) => state.block.count ?? 0); const { isEnded, transactionDate } = useFutureSwapDate( executionBlock, - blockCount + blockCount, ); const [amountToWithdraw, setAmountToWithdraw] = useState(""); const [fee, setFee] = useState(new BigNumber(0.0001)); @@ -94,8 +91,8 @@ export function WithdrawFutureSwapScreen(props: Props): JSX.Element { hasError ? TransactionCardStatus.Error : isInputFocus - ? TransactionCardStatus.Active - : TransactionCardStatus.Default + ? TransactionCardStatus.Active + : TransactionCardStatus.Default, ); }, [hasError, isInputFocus]); @@ -111,7 +108,7 @@ export function WithdrawFutureSwapScreen(props: Props): JSX.Element { remainingAmountInUSD: getTokenPrice( source.symbol, new BigNumber(source.amount).minus(BigNumber.max(amountToWithdraw, 0)), - false + false, ), }; }, [source, amountToWithdraw]); @@ -212,7 +209,7 @@ export function WithdrawFutureSwapScreen(props: Props): JSX.Element { type: "wallet_toast", placement: "top", duration: TOAST_DURATION, - } + }, ); } @@ -227,7 +224,7 @@ export function WithdrawFutureSwapScreen(props: Props): JSX.Element { tokenBSymbol={destination.displaySymbol} headerLabel={translate( "screens/WithdrawFutureSwapScreen", - "View swap info" + "View swap info", )} onPress={expandModal} testID="view_swap_info" @@ -237,7 +234,7 @@ export function WithdrawFutureSwapScreen(props: Props): JSX.Element { testID="withdraw_title" text={translate( "screens/WithdrawFutureSwapScreen", - "I WANT TO WITHDRAW" + "I WANT TO WITHDRAW", )} /> {translate( "screens/WithdrawFutureSwapScreen", - "Insufficient Balance" + "Insufficient Balance", )} ) : ( @@ -288,7 +285,7 @@ export function WithdrawFutureSwapScreen(props: Props): JSX.Element { testID="text_inline" label={`${translate( "screens/WithdrawFutureSwapScreen", - "Withdraw from" + "Withdraw from", )}: `} content={source.amount} suffix={` ${source.displaySymbol}`} @@ -308,7 +305,7 @@ export function WithdrawFutureSwapScreen(props: Props): JSX.Element { lhs={{ value: translate( "screens/WithdrawFutureSwapScreen", - "Transaction fee" + "Transaction fee", ), testID: "transaction_fee_label", themedProps: { @@ -328,14 +325,14 @@ export function WithdrawFutureSwapScreen(props: Props): JSX.Element { {translate( "screens/WithdrawFutureSwapScreen", - "Review full details in the next screen" + "Review full details in the next screen", )} diff --git a/mobile-app/app/screens/AppNavigator/screens/Settings/SettingsScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Settings/SettingsScreen.tsx index f51a5dc706..b3b4e5e2ba 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Settings/SettingsScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Settings/SettingsScreen.tsx @@ -16,7 +16,7 @@ import { } from "@waveshq/walletkit-ui"; import { StackScreenProps } from "@react-navigation/stack"; import { authentication, Authentication } from "@store/authentication"; -import { ocean } from "@waveshq/walletkit-ui/dist/store"; +import { ocean } from "@waveshq/walletkit-ui/store"; import { tailwind } from "@tailwind"; import { getAppLanguages, translate } from "@translations"; import { useCallback } from "react"; diff --git a/mobile-app/app/screens/AppNavigator/screens/Settings/components/ResetButton.tsx b/mobile-app/app/screens/AppNavigator/screens/Settings/components/ResetButton.tsx index ad61313aa5..53a1510c13 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Settings/components/ResetButton.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Settings/components/ResetButton.tsx @@ -8,10 +8,7 @@ import { useLogger } from "@shared-contexts/NativeLoggingProvider"; import { useAppDispatch } from "@hooks/useAppDispatch"; import { useSelector } from "react-redux"; import { RootState } from "@store"; -import { - hasTxQueued, - hasOceanTXQueued, -} from "@waveshq/walletkit-ui/dist/store"; +import { hasTxQueued, hasOceanTXQueued } from "@waveshq/walletkit-ui/store"; import { useServiceProviderContext } from "@waveshq/walletkit-ui"; import { ButtonV2 } from "@components/ButtonV2"; import { diff --git a/mobile-app/app/screens/AppNavigator/screens/Settings/screens/NetworkDetails.test.tsx b/mobile-app/app/screens/AppNavigator/screens/Settings/screens/NetworkDetails.test.tsx index fca7094ef1..fa35884388 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Settings/screens/NetworkDetails.test.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Settings/screens/NetworkDetails.test.tsx @@ -2,7 +2,7 @@ import { configureStore } from "@reduxjs/toolkit"; import { Provider } from "react-redux"; import { render } from "@testing-library/react-native"; import { RootState } from "@store"; -import { block } from "@waveshq/walletkit-ui/dist/store/block"; +import { block } from "@waveshq/walletkit-ui/store/block"; import { NetworkDetails } from "./NetworkDetails"; jest.mock("@shared-contexts/DeFiScanContext"); diff --git a/mobile-app/app/screens/AppNavigator/screens/Settings/screens/NetworkSelectionScreen.test.tsx b/mobile-app/app/screens/AppNavigator/screens/Settings/screens/NetworkSelectionScreen.test.tsx index 311ba1e285..32038d2c7d 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Settings/screens/NetworkSelectionScreen.test.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Settings/screens/NetworkSelectionScreen.test.tsx @@ -1,10 +1,6 @@ import { configureStore } from "@reduxjs/toolkit"; import { RootState } from "@store"; -import { - ocean, - block, - transactionQueue, -} from "@waveshq/walletkit-ui/dist/store"; +import { ocean, block, transactionQueue } from "@waveshq/walletkit-ui/store"; import { render } from "@testing-library/react-native"; import { Provider } from "react-redux"; import { NetworkSelectionScreen } from "./NetworkSelectionScreen"; @@ -48,7 +44,7 @@ describe("onboarding network selection screen", () => { const rendered = render( - + , ); expect(rendered.toJSON()).toMatchSnapshot(); }); diff --git a/mobile-app/app/screens/AppNavigator/screens/Settings/screens/NetworkSelectionScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Settings/screens/NetworkSelectionScreen.tsx index bfacccf6f2..4dc5361aa2 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Settings/screens/NetworkSelectionScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Settings/screens/NetworkSelectionScreen.tsx @@ -19,10 +19,7 @@ import { NumberRowV2 } from "@components/NumberRowV2"; import { getEnvironment } from "@waveshq/walletkit-core"; import { getReleaseChannel } from "@api/releaseChannel"; import { NetworkItemRow } from "@components/NetworkItemRow"; -import { - hasTxQueued, - hasOceanTXQueued, -} from "@waveshq/walletkit-ui/dist/store"; +import { hasTxQueued, hasOceanTXQueued } from "@waveshq/walletkit-ui/store"; export function NetworkSelectionScreen(): JSX.Element { const networks = getEnvironment(getReleaseChannel()).networks; @@ -32,10 +29,10 @@ export function NetworkSelectionScreen(): JSX.Element { lastSuccessfulSync, } = useSelector((state: RootState) => state.block); const hasPendingJob = useSelector((state: RootState) => - hasTxQueued(state.transactionQueue) + hasTxQueued(state.transactionQueue), ); const hasPendingBroadcastJob = useSelector((state: RootState) => - hasOceanTXQueued(state.ocean) + hasOceanTXQueued(state.ocean), ); const syncFormattedDate = lastSuccessfulSync != null ? dayjs(lastSuccessfulSync).format("lll") : ""; @@ -50,7 +47,7 @@ export function NetworkSelectionScreen(): JSX.Element { testID="onboarding_network_selection_screen_title" text={translate( "screens/OnboardingNetworkSelectScreen", - "SELECT NETWORK" + "SELECT NETWORK", )} /> @@ -94,7 +91,7 @@ export function NetworkSelectionScreen(): JSX.Element { }} containerStyle={{ style: tailwind( - "pb-4.5 border-b-0.5 flex-row items-start w-full bg-transparent" + "pb-4.5 border-b-0.5 flex-row items-start w-full bg-transparent", ), light: tailwind("border-mono-light-v2-300"), dark: tailwind("border-mono-dark-v2-300"), @@ -116,7 +113,7 @@ export function NetworkSelectionScreen(): JSX.Element { }} containerStyle={{ style: tailwind( - "pt-4.5 flex-row items-start w-full bg-transparent" + "pt-4.5 flex-row items-start w-full bg-transparent", ), light: tailwind("bg-transparent"), dark: tailwind("bg-transparent"), @@ -140,7 +137,7 @@ function BlocksInfoRow({ blockCount }: { blockCount?: number }): JSX.Element { return ( @@ -196,7 +193,7 @@ function TransactionOngoingMessage(): JSX.Element { {translate( "screens/NetworkDetails", - "Network selection is currently unavailable due to ongoing transaction(s)." + "Network selection is currently unavailable due to ongoing transaction(s).", )} diff --git a/mobile-app/app/screens/AppNavigator/screens/Transactions/TransactionsScreen.tsx b/mobile-app/app/screens/AppNavigator/screens/Transactions/TransactionsScreen.tsx index 5ac67eb9a3..d266820940 100644 --- a/mobile-app/app/screens/AppNavigator/screens/Transactions/TransactionsScreen.tsx +++ b/mobile-app/app/screens/AppNavigator/screens/Transactions/TransactionsScreen.tsx @@ -4,7 +4,7 @@ import { } from "@components/SkeletonLoader"; import { useThemeContext } from "@waveshq/walletkit-ui"; import { useWalletContext } from "@shared-contexts/WalletContext"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { MaterialIcons } from "@expo/vector-icons"; import { NavigationProp, @@ -56,7 +56,7 @@ export function TransactionsScreen(): JSX.Element { const [transactions, setTransactions] = useState([]); const [loadingState, setLoadingState] = useState("idle"); const [loadMoreToken, setLoadMoreToken] = useState( - undefined + undefined, ); const ref = useRef(null); useScrollToTop(ref); @@ -83,7 +83,7 @@ export function TransactionsScreen(): JSX.Element { .then(async (addActivities) => { if (typeof loadMoreToken === "string") { setTransactions( - transactions.concat(activitiesToViewModel(addActivities, isLight)) + transactions.concat(activitiesToViewModel(addActivities, isLight)), ); } else { setTransactions(activitiesToViewModel(addActivities, isLight)); diff --git a/mobile-app/app/screens/PlaygroundNavigator/sections/PlaygroundOperations.tsx b/mobile-app/app/screens/PlaygroundNavigator/sections/PlaygroundOperations.tsx index 934439e354..ccbd2e5fe5 100644 --- a/mobile-app/app/screens/PlaygroundNavigator/sections/PlaygroundOperations.tsx +++ b/mobile-app/app/screens/PlaygroundNavigator/sections/PlaygroundOperations.tsx @@ -2,11 +2,11 @@ import { View } from "@components"; import { PlaygroundTitle } from "@screens/PlaygroundNavigator/components/PlaygroundTitle"; import { useWalletContext } from "@shared-contexts/WalletContext"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { usePlaygroundContext } from "@waveshq/walletkit-ui"; import { useEffect, useState } from "react"; import { WalletAddressIndexPersistence } from "@api/wallet/address_index"; -import { fetchTokens } from "@waveshq/walletkit-ui/dist/store"; +import { fetchTokens } from "@waveshq/walletkit-ui/store"; import { PlaygroundConnectionStatus, PlaygroundStatusType, @@ -22,7 +22,7 @@ export function PlaygroundOperations(): JSX.Element { const dispatch = useAppDispatch(); const { api, rpc } = usePlaygroundContext(); const [status, setStatus] = useState( - PlaygroundConnectionStatus.loading + PlaygroundConnectionStatus.loading, ); useEffect(() => { @@ -51,7 +51,7 @@ export function PlaygroundOperations(): JSX.Element { fetchTokens({ client, address, - }) + }), ); }, rhsChildren: (): JSX.Element => { @@ -73,7 +73,7 @@ export function PlaygroundOperations(): JSX.Element { await rpc.call( "generatetoaddress", [10, "mswsMVsyGMj1FzDMbbxw2QW3KvQAv2FKiy"], - "number" + "number", ); }, rhsChildren: (): JSX.Element => { diff --git a/mobile-app/app/screens/TransactionAuthorization/PasscodePrompt.tsx b/mobile-app/app/screens/TransactionAuthorization/PasscodePrompt.tsx index 49e74bd1b4..7b4d260f1d 100644 --- a/mobile-app/app/screens/TransactionAuthorization/PasscodePrompt.tsx +++ b/mobile-app/app/screens/TransactionAuthorization/PasscodePrompt.tsx @@ -5,7 +5,7 @@ import { ThemedTouchableOpacityV2, ThemedViewV2, } from "@components/themed"; -import { DfTxSigner } from "@waveshq/walletkit-ui/dist/store"; +import { DfTxSigner } from "@waveshq/walletkit-ui/store"; import { tailwind } from "@tailwind"; import { translate } from "@translations"; import { Platform, SafeAreaView, View } from "react-native"; diff --git a/mobile-app/app/screens/TransactionAuthorization/TransactionAuthorization.tsx b/mobile-app/app/screens/TransactionAuthorization/TransactionAuthorization.tsx index fad8a48496..b037b91674 100644 --- a/mobile-app/app/screens/TransactionAuthorization/TransactionAuthorization.tsx +++ b/mobile-app/app/screens/TransactionAuthorization/TransactionAuthorization.tsx @@ -19,7 +19,7 @@ import { useWalletPersistenceContext, WalletType, } from "@waveshq/walletkit-ui"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; import { RootState } from "@store"; import { authentication as authenticationStore } from "@store/authentication"; import { @@ -27,7 +27,7 @@ import { DfTxSigner, first, transactionQueue, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { translate } from "@translations"; import { useLogger } from "@shared-contexts/NativeLoggingProvider"; import { diff --git a/mobile-app/app/screens/TransactionAuthorization/api/transaction_signer.ts b/mobile-app/app/screens/TransactionAuthorization/api/transaction_signer.ts index 5f45e7b231..35971ca345 100644 --- a/mobile-app/app/screens/TransactionAuthorization/api/transaction_signer.ts +++ b/mobile-app/app/screens/TransactionAuthorization/api/transaction_signer.ts @@ -1,4 +1,4 @@ -import { DfTxSigner } from "@waveshq/walletkit-ui/dist/store"; +import { DfTxSigner } from "@waveshq/walletkit-ui/store"; import { WhaleWalletAccount } from "@defichain/whale-api-wallet"; import { CTransactionSegWit } from "@defichain/jellyfish-transaction"; import { Authentication } from "@store/authentication"; @@ -14,7 +14,7 @@ export async function execWithAutoRetries( promptPromise: () => Promise, onAutoRetry: (attempts: number) => Promise, retries: number = 0, - logger: NativeLoggingProps + logger: NativeLoggingProps, ): Promise { try { return await promptPromise(); @@ -26,7 +26,7 @@ export async function execWithAutoRetries( promptPromise, onAutoRetry, retries, - logger + logger, ); } throw e; @@ -39,13 +39,13 @@ export async function signTransaction( account: WhaleWalletAccount, onAutoRetry: (attempts: number) => Promise, retries: number = 0, - logger: NativeLoggingProps + logger: NativeLoggingProps, ): Promise { return await execWithAutoRetries( async () => await tx.sign(account), onAutoRetry, retries, - logger + logger, ); } @@ -55,7 +55,7 @@ export async function authenticateFor( authentication: Authentication, onAutoRetry: (attempts: number) => Promise, retries: number = 0, - logger: NativeLoggingProps + logger: NativeLoggingProps, ): Promise { const customJob = async (): Promise => { const passphrase = await promptPassphrase(); @@ -71,7 +71,7 @@ export function alertUnlinkWallet(): void { title: translate("screens/PinConfirmation", "Wallet Unlinked"), message: translate( "screens/PinConfirmation", - "Your wallet was unlinked for your safety due to successive passcode failures. Please use recovery words to restore and set up your wallet again." + "Your wallet was unlinked for your safety due to successive passcode failures. Please use recovery words to restore and set up your wallet again.", ), buttons: [ { diff --git a/mobile-app/app/screens/WalletNavigator/screens/CreateWallet/OnboardingNetworkSelectScreen.test.tsx b/mobile-app/app/screens/WalletNavigator/screens/CreateWallet/OnboardingNetworkSelectScreen.test.tsx index c1b25af564..9449726111 100644 --- a/mobile-app/app/screens/WalletNavigator/screens/CreateWallet/OnboardingNetworkSelectScreen.test.tsx +++ b/mobile-app/app/screens/WalletNavigator/screens/CreateWallet/OnboardingNetworkSelectScreen.test.tsx @@ -1,6 +1,6 @@ import { configureStore } from "@reduxjs/toolkit"; import { RootState } from "@store"; -import { block } from "@waveshq/walletkit-ui/dist/store/block"; +import { block } from "@waveshq/walletkit-ui/store/block"; import { render } from "@testing-library/react-native"; import { Provider } from "react-redux"; import { OnboardingNetworkSelectScreen } from "./OnboardingNetworkSelectScreen"; @@ -32,7 +32,7 @@ describe("onboarding network selection screen", () => { const rendered = render( - + , ); expect(rendered.toJSON()).toMatchSnapshot(); }); diff --git a/package-lock.json b/package-lock.json index 2cb9c42442..2c1d24d0b4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,9 +22,12 @@ "@react-navigation/stack": "^6.3.29", "@reduxjs/toolkit": "^1.9.7", "@shopify/flash-list": "1.6.3", + "@stickyjs/eslint-config": "^1.3.2", + "@stickyjs/jest": "^1.3.2", + "@stickyjs/turbo": "^1.3.2", "@waveshq/standard-defichain-jellyfishsdk": "^2.20.0", - "@waveshq/walletkit-core": "^1.3.10", - "@waveshq/walletkit-ui": "^1.3.10", + "@waveshq/standard-web": "^4.0.1", + "@waveshq/standard-web-linter": "^4.0.1", "bignumber.js": "^9.1.2", "buffer": "^6.0.3", "classnames": "^2.3.2", @@ -51,6 +54,7 @@ "expo-updates": "~0.24.12", "expo-web-browser": "~12.8.2", "i18n-js": "^3.9.2", + "immer": "^9.0.21", "install": "^0.13.0", "lodash": "^4.17.21", "lru-cache": "^7.18.3", @@ -79,11 +83,13 @@ "react-overlays": "^5.2.1", "react-qr-code": "^2.0.12", "react-redux": "^8.1.3", + "reselect": "^4.1.8", "semver": "^7.5.4", "smart-buffer": "^4.2.0", "stream-browserify": "^3.0.0", "tailwind-rn": "^3.0.1", - "tailwindcss": "^2.2.19" + "tailwindcss": "^2.2.19", + "testcontainers": "^9.12.0" }, "devDependencies": { "@babel/core": "^7.23.2", @@ -92,16 +98,22 @@ "@expo/metro-config": "~0.17.1", "@expo/metro-runtime": "^3.1.3", "@testing-library/cypress": "^10.0.1", + "@testing-library/jest-dom": "^5.17.0", + "@testing-library/react": "^14.0.0", + "@testing-library/react-hooks": "^7.0.2", "@testing-library/react-native": "^11.5.4", "@types/find-in-files": "^0.5.2", "@types/i18n-js": "^3.8.7", "@types/jest": "^29.5.6", "@types/lodash": "^4.14.200", "@types/randomcolor": "^0.5.8", + "@types/react": "17.0.0", "@types/react-native": "~0.72.5", "@types/react-native-loading-spinner-overlay": "^0.5.4", "@types/react-test-renderer": "^18.0.5", "@types/semver": "^7.5.4", + "@waveshq/standard-defichain-jellyfishsdk": "^4.0.1", + "@waveshq/standard-prettier": "^4.0.1", "babel-plugin-istanbul": "^6.1.1", "babel-plugin-module-resolver": "^5.0.0", "babel-plugin-transform-remove-console": "^6.9.4", @@ -109,19 +121,10 @@ "cypress": "^13.7.0", "cypress-image-diff-js": "^1.32.0", "eslint": "^8.52.0", - "eslint-config-airbnb": "^19.0.4", - "eslint-config-airbnb-typescript": "^17.1.0", - "eslint-config-node": "^4.1.0", - "eslint-config-prettier": "^9.0.0", - "eslint-plugin-cypress": "^2.15.1", - "eslint-plugin-jest": "27.4.3", - "eslint-plugin-prettier": "^5.0.1", - "eslint-plugin-react": "^7.33.2", - "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-react-native": "^4.1.0", "find-in-files": "^0.5.0", "husky": "^8.0.3", "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", "jest-expo": "~50.0.3", "lint-staged": "^14.0.1", "randomcolor": "^0.6.2", @@ -133,6 +136,9 @@ "typescript": "^5.3.0", "wait-on": "^7.2.0", "webpack-merge": "^5.10.0" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -143,10 +149,19 @@ "node": ">=0.10.0" } }, + "node_modules/@adobe/css-tools": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.0.tgz", + "integrity": "sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@adraffy/ens-normalize": { "version": "1.10.1", "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", - "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==" + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", + "dev": true, + "license": "MIT" }, "node_modules/@ampproject/remapping": { "version": "2.3.0", @@ -2648,61 +2663,71 @@ } }, "node_modules/@defichain/jellyfish-address": { - "version": "4.0.0-beta.14.1", - "resolved": "https://registry.npmjs.org/@defichain/jellyfish-address/-/jellyfish-address-4.0.0-beta.14.1.tgz", - "integrity": "sha512-JQR90siVgN/w9ozY0ob/wYVl4uBk9B8hQSnDTNqd8lOn6K19qbnbRuGs9wD8l1O6xGg0lXCySc2oBytR51VKfQ==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@defichain/jellyfish-address/-/jellyfish-address-4.0.7.tgz", + "integrity": "sha512-ZDt0x/0mxtgRAUJRDo1KV6aTByIYgpW5sJwkntx4Dy2rL1AFjN0+Qy2bgDSJitb44fqYeyh9IbfIMUGKU1t/nA==", + "dev": true, + "license": "MIT", "dependencies": { - "@defichain/jellyfish-crypto": "4.0.0-beta.14.1", - "@defichain/jellyfish-network": "4.0.0-beta.14.1", - "@defichain/jellyfish-transaction": "4.0.0-beta.14.1", + "@defichain/jellyfish-crypto": "4.0.7", + "@defichain/jellyfish-network": "4.0.7", + "@defichain/jellyfish-transaction": "4.0.7", "bech32": "^2.0.0", "bs58": "^4.0.1" }, "peerDependencies": { - "defichain": "^4.0.0-beta.14.1" + "defichain": "^4.0.7" } }, "node_modules/@defichain/jellyfish-api-core": { - "version": "4.0.0-beta.14.1", - "resolved": "https://registry.npmjs.org/@defichain/jellyfish-api-core/-/jellyfish-api-core-4.0.0-beta.14.1.tgz", - "integrity": "sha512-Eob/zdPwVipk0tNXCWjnNiGp2GG8jYZOCmA8f5XgR5AkoOar1DyT6oSO8Z3rZ5/6DvoicJnc9VUH2M3z48cFsg==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@defichain/jellyfish-api-core/-/jellyfish-api-core-4.0.7.tgz", + "integrity": "sha512-g0hn2xwELGPn8QvCeEOumKpUXUmyMWDKWn67nyj4d59rzrV88FEtFqWJGZZ/dS49Q1gWLL2dkxbxQ0tO7LRDwg==", + "dev": true, + "license": "MIT", "dependencies": { - "@defichain/jellyfish-json": "4.0.0-beta.14.1" + "@defichain/jellyfish-json": "4.0.7" }, "peerDependencies": { - "defichain": "^4.0.0-beta.14.1" + "defichain": "^4.0.7" } }, "node_modules/@defichain/jellyfish-api-jsonrpc": { - "version": "4.0.0-beta.14.1", - "resolved": "https://registry.npmjs.org/@defichain/jellyfish-api-jsonrpc/-/jellyfish-api-jsonrpc-4.0.0-beta.14.1.tgz", - "integrity": "sha512-FrU/OpzIJes6Ul8pNpl6tuEIO6Grfy3ot+3Z/NR1fmDd/9aJtGWPf6K1tqbDdGWlo7kC3nkIUuHRuxMDLnwU9Q==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@defichain/jellyfish-api-jsonrpc/-/jellyfish-api-jsonrpc-4.0.7.tgz", + "integrity": "sha512-wVLRss+kiPnnLnQcF1MzA/zx2m2Ebk+DjvdX3wXcEownNfb8cM+Tj7ypHl5EDvDfCScaWJI59aa1VjfskpKhIA==", + "dev": true, + "license": "MIT", "dependencies": { - "@defichain/jellyfish-api-core": "4.0.0-beta.14.1", + "@defichain/jellyfish-api-core": "4.0.7", "abort-controller": "^3.0.0", "cross-fetch": "^3.1.5" }, "peerDependencies": { - "defichain": "^4.0.0-beta.14.1" + "defichain": "^4.0.7" } }, "node_modules/@defichain/jellyfish-buffer": { - "version": "4.0.0-beta.14.1", - "resolved": "https://registry.npmjs.org/@defichain/jellyfish-buffer/-/jellyfish-buffer-4.0.0-beta.14.1.tgz", - "integrity": "sha512-b0E+QvU7dWbiKr1I583amq/kVS19ltgTxKLUJxwwwii3COszXUJYeZ5PQfZIqIn/jiX2dAxI4rXXKELBZh5FLA==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@defichain/jellyfish-buffer/-/jellyfish-buffer-4.0.7.tgz", + "integrity": "sha512-5yJ2t5WH1fuNC+TEkS5nTHJfKW2ORsaYrjAS5zMWsu71CwRDo/iIM/suaujqz3657BUhoB3CdbgGOpsHOXmXfQ==", + "dev": true, + "license": "MIT", "dependencies": { "bignumber.js": "^9.0.2", "bn.js": "^5.2.1", "smart-buffer": "^4.2.0" }, "peerDependencies": { - "defichain": "^4.0.0-beta.14.1" + "defichain": "^4.0.7" } }, "node_modules/@defichain/jellyfish-crypto": { - "version": "4.0.0-beta.14.1", - "resolved": "https://registry.npmjs.org/@defichain/jellyfish-crypto/-/jellyfish-crypto-4.0.0-beta.14.1.tgz", - "integrity": "sha512-wqiBaBYK2AvibFUTk4snyikhN29vdYt1ojeD4unMozWm9lI2223PzjwoOv5olSjKxyUf1XeNRLway6jaDx8WDQ==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@defichain/jellyfish-crypto/-/jellyfish-crypto-4.0.7.tgz", + "integrity": "sha512-3JzS4QKjNhE/i8XrT2/W9IYgjjHc0SKg9Lu7X5REVtmkIe71gILluvI8g2M0duNytpu+qlmsOL5vYO4cCyXzVA==", + "dev": true, + "license": "MIT", "dependencies": { "bech32": "^2.0.0", "bip66": "^1.1.5", @@ -2715,78 +2740,90 @@ "wif": "^2.0.6" }, "peerDependencies": { - "defichain": "^4.0.0-beta.14.1" + "defichain": "^4.0.7" } }, "node_modules/@defichain/jellyfish-json": { - "version": "4.0.0-beta.14.1", - "resolved": "https://registry.npmjs.org/@defichain/jellyfish-json/-/jellyfish-json-4.0.0-beta.14.1.tgz", - "integrity": "sha512-SIyLc+fhTXsueBPVDzlingodQybz44q1ulrMQjF/6ziqTYU1kbYdnkCjlvDekDw1UsSodN/QRm5fcR6TANpgaQ==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@defichain/jellyfish-json/-/jellyfish-json-4.0.7.tgz", + "integrity": "sha512-eMH1NEMhiSHyUMMDit1qfXeMK06spBUwoQ9VPjFKax3nLhzmQEuM/lbZO47558IvtJpqDz7tuTo39/2SJFlhmw==", + "dev": true, + "license": "MIT", "dependencies": { "@types/lossless-json": "^1.0.1", "bignumber.js": "^9.0.2", "lossless-json": "^1.0.5" }, "peerDependencies": { - "defichain": "^4.0.0-beta.14.1" + "defichain": "^4.0.7" } }, "node_modules/@defichain/jellyfish-network": { - "version": "4.0.0-beta.14.1", - "resolved": "https://registry.npmjs.org/@defichain/jellyfish-network/-/jellyfish-network-4.0.0-beta.14.1.tgz", - "integrity": "sha512-NzE+Rvl8kIadjv0sp6G2UWAkmla019Cvi3kMg9tMOj6X3F3bI0h0xufXNfb6rYKtZU8/0QFypatu8eYmxXm2JQ==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@defichain/jellyfish-network/-/jellyfish-network-4.0.7.tgz", + "integrity": "sha512-f2pwHgao3k+4MGTZj8jc6P4TDaxnQgYRihe7bEPnXZkLc51j4fk9BZlJlgNgQjpWgImzj0BaODBMjwatPiHYdA==", + "dev": true, + "license": "MIT", "dependencies": { "bignumber.js": "^9.0.2" }, "peerDependencies": { - "defichain": "^4.0.0-beta.14.1" + "defichain": "^4.0.7" } }, "node_modules/@defichain/jellyfish-testing": { - "version": "4.0.0-beta.14.1", - "resolved": "https://registry.npmjs.org/@defichain/jellyfish-testing/-/jellyfish-testing-4.0.0-beta.14.1.tgz", - "integrity": "sha512-TR7QPdGD9TkGx7jp0+3I/6MjGIYmYjmGY2o8MxrBnk2Vk8nDR1twpndgAl+0ROtVdEcE3un6v6Wita2dr14C4g==", - "dependencies": { - "@defichain/jellyfish-api-jsonrpc": "4.0.0-beta.14.1", - "@defichain/jellyfish-crypto": "4.0.0-beta.14.1", - "@defichain/jellyfish-network": "4.0.0-beta.14.1", - "@defichain/testcontainers": "4.0.0-beta.14.1", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@defichain/jellyfish-testing/-/jellyfish-testing-4.0.7.tgz", + "integrity": "sha512-wdBYIGwOFyElie+0vo7D6jA5yKEc/EhDXgFJytFvjia41fTYxlIzAcgoJlPtwS9AQIPJTFyTaNQkOz7dxZp0hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@defichain/jellyfish-api-jsonrpc": "4.0.7", + "@defichain/jellyfish-crypto": "4.0.7", + "@defichain/jellyfish-network": "4.0.7", + "@defichain/testcontainers": "4.0.7", "cross-fetch": "^3.1.5" }, "peerDependencies": { - "defichain": "^4.0.0-beta.14.1" + "defichain": "^4.0.7" } }, "node_modules/@defichain/jellyfish-transaction": { - "version": "4.0.0-beta.14.1", - "resolved": "https://registry.npmjs.org/@defichain/jellyfish-transaction/-/jellyfish-transaction-4.0.0-beta.14.1.tgz", - "integrity": "sha512-R9i/oaYPqfUTpJFmAjAdAZ+r2i84/SP8N0bg/hRAqhnxsdSMIZRGaBzT1dBLB385k31S8uEoPoVElGdBL0/8/A==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@defichain/jellyfish-transaction/-/jellyfish-transaction-4.0.7.tgz", + "integrity": "sha512-TbKlhIJ7cJL5VcXTXO8XtyGAXG5RyHwo81M40+0zNw7iELz60heqCP4HK/qQnqIvBNACDmikQKZFOW+P+3u3Zw==", + "dev": true, + "license": "MIT", "dependencies": { - "@defichain/jellyfish-buffer": "4.0.0-beta.14.1", - "@defichain/jellyfish-crypto": "4.0.0-beta.14.1" + "@defichain/jellyfish-buffer": "4.0.7", + "@defichain/jellyfish-crypto": "4.0.7" }, "peerDependencies": { - "defichain": "^4.0.0-beta.14.1" + "defichain": "^4.0.7" } }, "node_modules/@defichain/jellyfish-transaction-builder": { - "version": "4.0.0-beta.14.1", - "resolved": "https://registry.npmjs.org/@defichain/jellyfish-transaction-builder/-/jellyfish-transaction-builder-4.0.0-beta.14.1.tgz", - "integrity": "sha512-IIDv8wOxkHYRIjOI4DSRImZ5dfRf38ety3iQVlQem2klRobIoOMcs4K0X6OPAj+25RucYnrUqLAC9WlNKgp6NQ==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@defichain/jellyfish-transaction-builder/-/jellyfish-transaction-builder-4.0.7.tgz", + "integrity": "sha512-X9awqqUjQRWJU1PpJmW6/3+HcJbvtAY31rf8Lcw327Pa69xR5CMgQDdqcb4L7iEsp2wC3CXn1MWON5I3H78kpw==", + "dev": true, + "license": "MIT", "dependencies": { - "@defichain/jellyfish-crypto": "4.0.0-beta.14.1", - "@defichain/jellyfish-transaction": "4.0.0-beta.14.1", - "@defichain/jellyfish-transaction-signature": "4.0.0-beta.14.1", + "@defichain/jellyfish-crypto": "4.0.7", + "@defichain/jellyfish-transaction": "4.0.7", + "@defichain/jellyfish-transaction-signature": "4.0.7", "ethers": "^6.7.1" }, "peerDependencies": { - "defichain": "^4.0.0-beta.14.1" + "defichain": "^4.0.7" } }, "node_modules/@defichain/jellyfish-transaction-builder/node_modules/@noble/hashes": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "dev": true, + "license": "MIT", "engines": { "node": ">= 16" }, @@ -2797,17 +2834,22 @@ "node_modules/@defichain/jellyfish-transaction-builder/node_modules/@types/node": { "version": "18.15.13", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", - "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==" + "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==", + "dev": true, + "license": "MIT" }, "node_modules/@defichain/jellyfish-transaction-builder/node_modules/aes-js": { "version": "4.0.0-beta.5", "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", - "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==" + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==", + "dev": true, + "license": "MIT" }, "node_modules/@defichain/jellyfish-transaction-builder/node_modules/ethers": { - "version": "6.11.1", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.11.1.tgz", - "integrity": "sha512-mxTAE6wqJQAbp5QAe/+o+rXOID7Nw91OZXvgpjDa1r4fAbq2Nu314oEZSbjoRLacuCzs7kUC3clEvkCQowffGg==", + "version": "6.13.3", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.3.tgz", + "integrity": "sha512-/DzbZOLVtoO4fKvvQwpEucHAQgIwBGWuRvBdwE/lMXgXvvHHTSkn7XqAQ2b+gjJzZDJjWA9OD05bVceVOsBHbg==", + "dev": true, "funding": [ { "type": "individual", @@ -2818,6 +2860,7 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { "@adraffy/ens-normalize": "1.10.1", "@noble/curves": "1.2.0", @@ -2825,22 +2868,24 @@ "@types/node": "18.15.13", "aes-js": "4.0.0-beta.5", "tslib": "2.4.0", - "ws": "8.5.0" + "ws": "8.17.1" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@defichain/jellyfish-transaction-builder/node_modules/ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "dev": true, + "license": "MIT", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -2852,92 +2897,106 @@ } }, "node_modules/@defichain/jellyfish-transaction-signature": { - "version": "4.0.0-beta.14.1", - "resolved": "https://registry.npmjs.org/@defichain/jellyfish-transaction-signature/-/jellyfish-transaction-signature-4.0.0-beta.14.1.tgz", - "integrity": "sha512-aFsRpg9Tza+nH73KyvUGFYQ/ka5v1EhD7hu1XibIR3SLO6p6WV7xbhzmniDU3zobE6YFW2LPZBCMiEhqhqmyoQ==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@defichain/jellyfish-transaction-signature/-/jellyfish-transaction-signature-4.0.7.tgz", + "integrity": "sha512-B/pc1/zpCcbvMCdGfAyx4IEONP26VsMr4ytUdl9eLlrdlpERekyWsMrqUzS9+EV6OE03idCKNpafhjIC36fyLg==", + "dev": true, + "license": "MIT", "dependencies": { - "@defichain/jellyfish-buffer": "4.0.0-beta.14.1", - "@defichain/jellyfish-crypto": "4.0.0-beta.14.1", - "@defichain/jellyfish-transaction": "4.0.0-beta.14.1" + "@defichain/jellyfish-buffer": "4.0.7", + "@defichain/jellyfish-crypto": "4.0.7", + "@defichain/jellyfish-transaction": "4.0.7" }, "peerDependencies": { - "defichain": "^4.0.0-beta.14.1" + "defichain": "^4.0.7" } }, "node_modules/@defichain/jellyfish-wallet": { - "version": "4.0.0-beta.14.1", - "resolved": "https://registry.npmjs.org/@defichain/jellyfish-wallet/-/jellyfish-wallet-4.0.0-beta.14.1.tgz", - "integrity": "sha512-TuI4DG+4kZvUMRfiJ2K5ktSj6ERubTt/Lx8Pk5bKpbjKyvj7k9EgEGtFYOv35tgGzzAl0hj8kIXKEWrIOXGleQ==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@defichain/jellyfish-wallet/-/jellyfish-wallet-4.0.7.tgz", + "integrity": "sha512-aSuszIp3a3GUKD1HCKJXISzPVfpPmAS2C2zMd/G4zX6gTMnvgiM26skdrg2vVGVlZs2rf69xFsX5jhPUm/bNNA==", + "dev": true, + "license": "MIT", "dependencies": { - "@defichain/jellyfish-address": "4.0.0-beta.14.1", - "@defichain/jellyfish-crypto": "4.0.0-beta.14.1", - "@defichain/jellyfish-network": "4.0.0-beta.14.1", - "@defichain/jellyfish-transaction": "4.0.0-beta.14.1", - "@defichain/jellyfish-transaction-builder": "4.0.0-beta.14.1", - "@defichain/jellyfish-transaction-signature": "4.0.0-beta.14.1" + "@defichain/jellyfish-address": "4.0.7", + "@defichain/jellyfish-crypto": "4.0.7", + "@defichain/jellyfish-network": "4.0.7", + "@defichain/jellyfish-transaction": "4.0.7", + "@defichain/jellyfish-transaction-builder": "4.0.7", + "@defichain/jellyfish-transaction-signature": "4.0.7" }, "peerDependencies": { - "defichain": "^4.0.0-beta.14.1" + "defichain": "^4.0.7" } }, "node_modules/@defichain/jellyfish-wallet-encrypted": { - "version": "4.0.0-beta.14.1", - "resolved": "https://registry.npmjs.org/@defichain/jellyfish-wallet-encrypted/-/jellyfish-wallet-encrypted-4.0.0-beta.14.1.tgz", - "integrity": "sha512-4WBkWr4S2pjNhy94pK2RxA20vwR6j0Gy9lPwUjYWa2Zeq5qZ6TJ4614kS/IWyoPQAqy33CVNXkTauUtlbTH0uA==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@defichain/jellyfish-wallet-encrypted/-/jellyfish-wallet-encrypted-4.0.7.tgz", + "integrity": "sha512-+Z/mpqS/S60hyCPRb8aVl5fnOOCfElk3lrLCzhDO0OsICuejw/y7O2nMBfpYhQi5m1I1fWPvHJUSLXCOn7YWaw==", + "dev": true, + "license": "MIT", "dependencies": { - "@defichain/jellyfish-wallet-mnemonic": "4.0.0-beta.14.1", + "@defichain/jellyfish-wallet-mnemonic": "4.0.7", "scrypt-js": "^3.0.1" }, "peerDependencies": { - "defichain": "^4.0.0-beta.14.1" + "defichain": "^4.0.7" } }, "node_modules/@defichain/jellyfish-wallet-mnemonic": { - "version": "4.0.0-beta.14.1", - "resolved": "https://registry.npmjs.org/@defichain/jellyfish-wallet-mnemonic/-/jellyfish-wallet-mnemonic-4.0.0-beta.14.1.tgz", - "integrity": "sha512-z6S3/AUNhq1jUOOb0rPxpIsttn8IpkvHrdzqv7m6fdQdImmz2hgsM3Bk8+geqsVEhjxvfU7x8YknTzY4dZU1LQ==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@defichain/jellyfish-wallet-mnemonic/-/jellyfish-wallet-mnemonic-4.0.7.tgz", + "integrity": "sha512-kyi9ErxhxLuJUNoGnNa1gVygqXPa+xOSB2X1vIjTRvozeFmiaEE1Q0lJfvuqiyQaz7mQR1k/Rsv+AtXvrXie4w==", + "dev": true, + "license": "MIT", "dependencies": { - "@defichain/jellyfish-transaction": "4.0.0-beta.14.1", - "@defichain/jellyfish-wallet": "4.0.0-beta.14.1", + "@defichain/jellyfish-transaction": "4.0.7", + "@defichain/jellyfish-wallet": "4.0.7", "bip32": "^2.0.6", "bip39": "^3.0.4", "create-hmac": "^1.1.7" }, "peerDependencies": { - "defichain": "^4.0.0-beta.14.1" + "defichain": "^4.0.7" } }, "node_modules/@defichain/ocean-api-client": { - "version": "4.0.0-beta.14.1", - "resolved": "https://registry.npmjs.org/@defichain/ocean-api-client/-/ocean-api-client-4.0.0-beta.14.1.tgz", - "integrity": "sha512-TUc+y6GMO7KX7eqkZ4auuJuh/KRdywwMA/lklVK0S+I/kZXlcPJGtJyx8Doh+1A+KbjhKdVjUI7MHDjWC3CB1A==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@defichain/ocean-api-client/-/ocean-api-client-4.0.7.tgz", + "integrity": "sha512-9IHiHqI9FkgnNPC8wcnRiMvvNapdw0IS6yRDUNWWMKmy+va0sD4s1Iip3e+2aDba5ElhhkN5/jkVvMz64KyKRQ==", + "dev": true, + "license": "MIT", "dependencies": { "abort-controller": "^3.0.0", "cross-fetch": "^3.1.5", "url-search-params-polyfill": "8.1.1" }, "peerDependencies": { - "defichain": "^4.0.0-beta.14.1" + "defichain": "^4.0.7" } }, "node_modules/@defichain/playground-api-client": { - "version": "4.0.0-beta.14.1", - "resolved": "https://registry.npmjs.org/@defichain/playground-api-client/-/playground-api-client-4.0.0-beta.14.1.tgz", - "integrity": "sha512-MJi2H2w5jiZIwTRPaeKYYScWCLhiDZcVOuS7M4uJTF8K+Np+pyLEB/4rQ4GhQsf8yQKmJoCoHDksLqRiIcf/WA==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@defichain/playground-api-client/-/playground-api-client-4.0.7.tgz", + "integrity": "sha512-Z7Djk6ZdWYgAZs3RRtcBtL/UOY1sxgBAoUXBm0IYe4+U6TA3+KW+lslF3oHIpp2IeGYTnEPRHZ1Sx3ofZyQLiQ==", + "dev": true, + "license": "MIT", "dependencies": { - "@defichain/jellyfish-api-core": "4.0.0-beta.14.1", - "@defichain/ocean-api-client": "4.0.0-beta.14.1" + "@defichain/jellyfish-api-core": "4.0.7", + "@defichain/ocean-api-client": "4.0.7" }, "peerDependencies": { - "defichain": "^4.0.0-beta.14.1" + "defichain": "^4.0.7" } }, "node_modules/@defichain/testcontainers": { - "version": "4.0.0-beta.14.1", - "resolved": "https://registry.npmjs.org/@defichain/testcontainers/-/testcontainers-4.0.0-beta.14.1.tgz", - "integrity": "sha512-p4rKtgMtLj5vVTiBP2lWr+llaFG62uQB+4zZR1bjzQKG2GJu5L03D9kHYMPjk+Jl2rvqnVdiepc+LSyn6C9fbg==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@defichain/testcontainers/-/testcontainers-4.0.7.tgz", + "integrity": "sha512-OEFPYBXQWvH5iahyjycmcAUGKLtFTlk0mMA+evDNFEXbzL48oSI2Q9YnvbCWZpsPFXCBdjyBp5L1LmeNAoAp6A==", + "dev": true, + "license": "MIT", "dependencies": { - "@defichain/jellyfish-network": "4.0.0-beta.14.1", + "@defichain/jellyfish-network": "4.0.7", "cross-fetch": "^3.1.5", "dockerode": "^3.3.5", "tar-fs": "^2.1.1", @@ -2946,35 +3005,39 @@ }, "peerDependencies": { "@types/tar-fs": "^2.0.1", - "defichain": "^4.0.0-beta.14.1" + "defichain": "^4.0.7" } }, "node_modules/@defichain/whale-api-client": { - "version": "4.0.0-beta.14.1", - "resolved": "https://registry.npmjs.org/@defichain/whale-api-client/-/whale-api-client-4.0.0-beta.14.1.tgz", - "integrity": "sha512-Hn+/HUqP0YETLyfTxsU6OLorbf8IXGi6VXYYWjuqKHFVPS/z19nGFeHX39kx6eARs50l5UV83Br2FVU5blMQuQ==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@defichain/whale-api-client/-/whale-api-client-4.0.7.tgz", + "integrity": "sha512-4rQgyrRkXcJM9/48lbY3sGbjjbVRPSrlxdoX5FsUNw87hd1RcAhFlhKgXoOeH05vbDkozMeWTChzhV0nGUAqew==", + "dev": true, + "license": "MIT", "dependencies": { - "@defichain/jellyfish-api-core": "4.0.0-beta.14.1", - "@defichain/jellyfish-api-jsonrpc": "4.0.0-beta.14.1", + "@defichain/jellyfish-api-core": "4.0.7", + "@defichain/jellyfish-api-jsonrpc": "4.0.7", "abort-controller": "^3.0.0", "cross-fetch": "^3.1.5", "url-search-params-polyfill": "8.1.1" }, "peerDependencies": { - "defichain": "^4.0.0-beta.14.1" + "defichain": "^4.0.7" } }, "node_modules/@defichain/whale-api-wallet": { - "version": "4.0.0-beta.14.1", - "resolved": "https://registry.npmjs.org/@defichain/whale-api-wallet/-/whale-api-wallet-4.0.0-beta.14.1.tgz", - "integrity": "sha512-qr8eeueZK4obKgHiZX/ApkuyUMGVjmtOqyThs4XdEtAFFr4ziMExI6Xu5Ovhz1IRJU/ofGX2dAkRh6W6IAdgyQ==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@defichain/whale-api-wallet/-/whale-api-wallet-4.0.7.tgz", + "integrity": "sha512-pEd1m22H7R0Frf2B09IvyVES4+cceZ16bylMhT4bxkUX6RKKiX008AHvSRT4XsWQoFmUUW+pCi/zQsblD5JWhQ==", + "dev": true, + "license": "MIT", "dependencies": { - "@defichain/jellyfish-transaction-builder": "4.0.0-beta.14.1", - "@defichain/jellyfish-wallet": "4.0.0-beta.14.1", - "@defichain/whale-api-client": "4.0.0-beta.14.1" + "@defichain/jellyfish-transaction-builder": "4.0.7", + "@defichain/jellyfish-wallet": "4.0.7", + "@defichain/whale-api-client": "4.0.7" }, "peerDependencies": { - "defichain": "^4.0.0-beta.14.1" + "defichain": "^4.0.7" } }, "node_modules/@egjs/hammerjs": { @@ -6747,14 +6810,16 @@ } }, "node_modules/@next/env": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.0.1.tgz", - "integrity": "sha512-Ms8ZswqY65/YfcjrlcIwMPD7Rg/dVjdLapMcSHG26W6O67EJDF435ShW4H4LXi1xKO1oRc97tLXUpx8jpLe86A==" + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.1.4.tgz", + "integrity": "sha512-e7X7bbn3Z6DWnDi75UWn+REgAbLEqxI8Tq2pkFOFAMpWAWApz/YCUhtWMWn410h8Q2fYiYL7Yg5OlxMOCfFjJQ==", + "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.0.1.tgz", - "integrity": "sha512-bLjJMwXdzvhnQOnxvHoTTUh/+PYk6FF/DCgHi4BXwXCINer+o1ZYfL9aVeezj/oI7wqGJOqwGIXrlBvPbAId3w==", + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.0.2.tgz", + "integrity": "sha512-APrYFsXfAhnysycqxHcpg6Y4i7Ukp30GzVSZQRKT3OczbzkqGjt33vNhScmgoOXYBU1CfkwgtXmNxdiwv1jKmg==", + "license": "MIT", "dependencies": { "glob": "7.1.7" } @@ -6763,6 +6828,8 @@ "version": "7.1.7", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -6779,12 +6846,13 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.0.1.tgz", - "integrity": "sha512-JyxnGCS4qT67hdOKQ0CkgFTp+PXub5W1wsGvIq98TNbF3YEIN7iDekYhYsZzc8Ov0pWEsghQt+tANdidITCLaw==", + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.1.4.tgz", + "integrity": "sha512-ubmUkbmW65nIAOmoxT1IROZdmmJMmdYvXIe8211send9ZYJu+SqxSnJM4TrPj9wmL6g9Atvj0S/2cFmMSS99jg==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "darwin" @@ -6794,12 +6862,13 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.0.1.tgz", - "integrity": "sha512-625Z7bb5AyIzswF9hvfZWa+HTwFZw+Jn3lOBNZB87lUS0iuCYDHqk3ujuHCkiyPtSC0xFBtYDLcrZ11mF/ap3w==", + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.1.4.tgz", + "integrity": "sha512-b0Xo1ELj3u7IkZWAKcJPJEhBop117U78l70nfoQGo4xUSvv0PJSTaV4U9xQBLvZlnjsYkc8RwQN1HoH/oQmLlQ==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "darwin" @@ -6809,12 +6878,13 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.0.1.tgz", - "integrity": "sha512-iVpn3KG3DprFXzVHM09kvb//4CNNXBQ9NB/pTm8LO+vnnnaObnzFdS5KM+w1okwa32xH0g8EvZIhoB3fI3mS1g==", + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.1.4.tgz", + "integrity": "sha512-457G0hcLrdYA/u1O2XkRMsDKId5VKe3uKPvrKVOyuARa6nXrdhJOOYU9hkKKyQTMru1B8qEP78IAhf/1XnVqKA==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -6824,12 +6894,13 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.0.1.tgz", - "integrity": "sha512-mVsGyMxTLWZXyD5sen6kGOTYVOO67lZjLApIj/JsTEEohDDt1im2nkspzfV5MvhfS7diDw6Rp/xvAQaWZTv1Ww==", + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.1.4.tgz", + "integrity": "sha512-l/kMG+z6MB+fKA9KdtyprkTQ1ihlJcBh66cf0HvqGP+rXBbOXX0dpJatjZbHeunvEHoBBS69GYQG5ry78JMy3g==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -6839,12 +6910,13 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.0.1.tgz", - "integrity": "sha512-wMqf90uDWN001NqCM/auRl3+qVVeKfjJdT9XW+RMIOf+rhUzadmYJu++tp2y+hUbb6GTRhT+VjQzcgg/QTD9NQ==", + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.1.4.tgz", + "integrity": "sha512-BapIFZ3ZRnvQ1uWbmqEGJuPT9cgLwvKtxhK/L2t4QYO7l+/DxXuIGjvp1x8rvfa/x1FFSsipERZK70pewbtJtw==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -6854,12 +6926,13 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.0.1.tgz", - "integrity": "sha512-ol1X1e24w4j4QwdeNjfX0f+Nza25n+ymY0T2frTyalVczUmzkVD7QGgPTZMHfR1aLrO69hBs0G3QBYaj22J5GQ==", + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.1.4.tgz", + "integrity": "sha512-mqVxTwk4XuBl49qn2A5UmzFImoL1iLm0KQQwtdRJRKl21ylQwwGCxJtIYo2rbfkZHoSKlh/YgztY0qH3wG1xIg==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -6869,12 +6942,13 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.0.1.tgz", - "integrity": "sha512-WEmTEeWs6yRUEnUlahTgvZteh5RJc4sEjCQIodJlZZ5/VJwVP8p2L7l6VhzQhT4h7KvLx/Ed4UViBdne6zpIsw==", + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.1.4.tgz", + "integrity": "sha512-xzxF4ErcumXjO2Pvg/wVGrtr9QQJLk3IyQX1ddAC/fi6/5jZCZ9xpuL9Tzc4KPWMFq8GGWFVDMshZOdHGdkvag==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "win32" @@ -6884,12 +6958,13 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.0.1.tgz", - "integrity": "sha512-oFpHphN4ygAgZUKjzga7SoH2VGbEJXZa/KL8bHCAwCjDWle6R1SpiGOdUdA8EJ9YsG1TYWpzY6FTbUA+iAJeww==", + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.1.4.tgz", + "integrity": "sha512-WZiz8OdbkpRw6/IU/lredZWKKZopUMhcI2F+XiMAcPja0uZYdMTZQRoQ0WZcvinn9xZAidimE7tN9W5v9Yyfyw==", "cpu": [ "ia32" ], + "license": "MIT", "optional": true, "os": [ "win32" @@ -6899,12 +6974,13 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.0.1.tgz", - "integrity": "sha512-FFp3nOJ/5qSpeWT0BZQ+YE1pSMk4IMpkME/1DwKBwhg4mJLB9L+6EXuJi4JEwaJdl5iN+UUlmUD3IsR1kx5fAg==", + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.1.4.tgz", + "integrity": "sha512-4Rto21sPfw555sZ/XNLqfxDUNeLhNYGO2dlPqsnuCg8N8a2a9u1ltqBOPQ4vj1Gf7eJC0W2hHG2eYUHuiXgY2w==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "win32" @@ -6917,6 +6993,8 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "dev": true, + "license": "MIT", "dependencies": { "@noble/hashes": "1.3.2" }, @@ -6928,6 +7006,8 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "dev": true, + "license": "MIT", "engines": { "node": ">= 16" }, @@ -6936,11 +7016,13 @@ } }, "node_modules/@noble/hashes": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", - "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz", + "integrity": "sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 16" + "node": "^14.21.3 || >=16" }, "funding": { "url": "https://paulmillr.com/funding/" @@ -6978,6 +7060,15 @@ "node": ">= 8" } }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "license": "MIT", + "engines": { + "node": ">=12.4.0" + } + }, "node_modules/@npmcli/fs": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", @@ -9119,9 +9210,10 @@ } }, "node_modules/@rushstack/eslint-patch": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.7.2.tgz", - "integrity": "sha512-RbhOOTCNoCrbfkRyoXODZp75MlpiHMgbE5MEBZAnnnLyQNgrigEj4p0lzsMDyc1zVsJDLrivB58tgg3emX0eEA==" + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz", + "integrity": "sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==", + "license": "MIT" }, "node_modules/@segment/loosely-validate-event": { "version": "2.0.0", @@ -9196,6 +9288,25 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@stickyjs/eslint-config": { + "version": "1.3.10", + "resolved": "https://registry.npmjs.org/@stickyjs/eslint-config/-/eslint-config-1.3.10.tgz", + "integrity": "sha512-ZeSme6LyWb8nv2VtLZnzKkZO2jm/+FYY+GuVGDsjcrhkLMdK4j8yQCe6HKGdOQWSts4xWv3ugezRwXrELqS9Tw==", + "dependencies": { + "@typescript-eslint/eslint-plugin": "^6.17.0", + "@typescript-eslint/parser": "^6.17.0", + "eslint": "^8.56.0", + "eslint-config-airbnb-base": "^15.0.0", + "eslint-config-airbnb-typescript": "^17.1.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-anti-trojan-source": "^1.1.1", + "eslint-plugin-check-file": "^2.6.2", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-no-only-tests": "^3.1.0", + "eslint-plugin-simple-import-sort": "^10.0.0", + "eslint-plugin-unused-imports": "^3.0.0" + } + }, "node_modules/@stickyjs/jest": { "version": "1.3.10", "resolved": "https://registry.npmjs.org/@stickyjs/jest/-/jest-1.3.10.tgz", @@ -9208,6 +9319,20 @@ "wait-for-expect": "^3.0.2" } }, + "node_modules/@stickyjs/turbo": { + "version": "1.3.10", + "resolved": "https://registry.npmjs.org/@stickyjs/turbo/-/turbo-1.3.10.tgz", + "integrity": "sha512-weAY9SVefZWjUTdhtFZKhiaFgxs6/9AV4KLDD0fwEDZSxAPRZU8zIYZ2t4+wdxx1WfjnIGEgz56V1Xcslqdi3g==", + "dependencies": { + "clipanion": "3.2.1" + }, + "bin": { + "sticky-turbo": "cli.js" + }, + "peerDependencies": { + "turbo": "*" + } + }, "node_modules/@swc/helpers": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.2.tgz", @@ -9357,6 +9482,151 @@ "node": ">=8" } }, + "node_modules/@testing-library/jest-dom": { + "version": "5.17.0", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz", + "integrity": "sha512-ynmNeT7asXyH3aSVv4vvX4Rb+0qjOhdNHnO/3vuZNqPmhDpV/+rCSGwQ7bLcmU2cJ4dvoheIO85LQj0IbJHEtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@adobe/css-tools": "^4.0.1", + "@babel/runtime": "^7.9.2", + "@types/testing-library__jest-dom": "^5.9.1", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.5.6", + "lodash": "^4.17.15", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=8", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@testing-library/jest-dom/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/react": { + "version": "14.3.1", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-14.3.1.tgz", + "integrity": "sha512-H99XjUhWQw0lTgyMN05W3xQG1Nh4lq574D8keFf1dDoNTJgp66VbJozRaczoF+wsiaPJNt/TcnfpLGufGxSrZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^9.0.0", + "@types/react-dom": "^18.0.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@testing-library/react-hooks": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@testing-library/react-hooks/-/react-hooks-7.0.2.tgz", + "integrity": "sha512-dYxpz8u9m4q1TuzfcUApqi8iFfR6R0FaMbr2hjZJy1uC8z+bO/K4v8Gs9eogGKYQop7QsrBTFkv/BCF7MzD2Cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5", + "@types/react": ">=16.9.0", + "@types/react-dom": ">=16.9.0", + "@types/react-test-renderer": ">=16.9.0", + "react-error-boundary": "^3.1.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0", + "react-test-renderer": ">=16.9.0" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-test-renderer": { + "optional": true + } + } + }, "node_modules/@testing-library/react-native": { "version": "11.5.4", "resolved": "https://registry.npmjs.org/@testing-library/react-native/-/react-native-11.5.4.tgz", @@ -9687,7 +9957,9 @@ "node_modules/@types/lossless-json": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@types/lossless-json/-/lossless-json-1.0.4.tgz", - "integrity": "sha512-eHhzo0p2p9On3cTr5X0Q0XsOjJxkqYzQi5Le5ObSiJjnLlGpDQvTcQEXknCkvKOFLBLa8ny4dgJKr0ADRV8yig==" + "integrity": "sha512-eHhzo0p2p9On3cTr5X0Q0XsOjJxkqYzQi5Le5ObSiJjnLlGpDQvTcQEXknCkvKOFLBLa8ny4dgJKr0ADRV8yig==", + "dev": true, + "license": "MIT" }, "node_modules/@types/minimist": { "version": "1.2.5", @@ -9729,19 +10001,20 @@ "dev": true }, "node_modules/@types/react": { - "version": "18.2.64", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.64.tgz", - "integrity": "sha512-MlmPvHgjj2p3vZaxbQgFUQFvD8QiZwACfGqEdDSWou5yISWxDQ4/74nCAwsUiX7UFLKZz3BbVSPj+YxeoGGCfg==", + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.0.tgz", + "integrity": "sha512-aj/L7RIMsRlWML3YB6KZiXB3fV2t41+5RBGYF8z+tAKU43Px8C3cYUZsDvf1/+Bm4FK21QWBrDutu8ZJ/70qOw==", + "license": "MIT", "dependencies": { "@types/prop-types": "*", - "@types/scheduler": "*", "csstype": "^3.0.2" } }, "node_modules/@types/react-dom": { - "version": "18.2.14", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.14.tgz", - "integrity": "sha512-V835xgdSVmyQmI1KLV2BEIUgqEuinxp9O4G6g3FqO/SqLac049E53aysv0oEFD2kHfejeKU+ZqL2bcFWj9gLAQ==", + "version": "18.2.15", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.15.tgz", + "integrity": "sha512-HWMdW+7r7MR5+PZqJF6YFNSCtjz1T0dsvo/f1BV6HkV+6erD/nA7wd9NM00KVG83zf2nJ7uATPO9ttdIPvi3gg==", + "license": "MIT", "dependencies": { "@types/react": "*" } @@ -9792,9 +10065,10 @@ } }, "node_modules/@types/scheduler": { - "version": "0.16.8", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", - "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-YIoDCTH3Af6XM5VuwGG/QL/CJqga1Zm3NkU3HZ4ZHK2fRMPYP1VczsTUqtsf43PH/iJNVlPHAo2oWX7BSdB2Hw==", + "license": "MIT" }, "node_modules/@types/semver": { "version": "7.5.8", @@ -9846,6 +10120,8 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/tar-fs/-/tar-fs-2.0.4.tgz", "integrity": "sha512-ipPec0CjTmVDWE+QKr9cTmIIoTl7dFG/yARCM5MqK8i6CNLIG1P8x4kwDsOQY1ChZOZjH0wO9nvfgBvWl4R3kA==", + "dev": true, + "license": "MIT", "peer": true, "dependencies": { "@types/node": "*", @@ -9856,11 +10132,23 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/@types/tar-stream/-/tar-stream-3.1.3.tgz", "integrity": "sha512-Zbnx4wpkWBMBSu5CytMbrT5ZpMiF55qgM+EpHzR4yIDu7mv52cej8hTkOc6K+LzpkOAbxwn/m7j3iO+/l42YkQ==", + "dev": true, + "license": "MIT", "peer": true, "dependencies": { "@types/node": "*" } }, + "node_modules/@types/testing-library__jest-dom": { + "version": "5.14.9", + "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.9.tgz", + "integrity": "sha512-FSYhIjFlfOpGSRyVoMBMuS3ws5ehFQODymf3vlI7U1K8c7PHwWwFY7VREfmsuzHSOnoKs/9/Y983ayOs7eRzqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/jest": "*" + } + }, "node_modules/@types/tough-cookie": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", @@ -9903,7 +10191,6 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", - "peer": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", "@typescript-eslint/scope-manager": "6.21.0", @@ -9981,7 +10268,6 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", - "peer": true, "dependencies": { "@typescript-eslint/typescript-estree": "6.21.0", "@typescript-eslint/utils": "6.21.0", @@ -10069,7 +10355,6 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", @@ -10136,91 +10421,67 @@ } }, "node_modules/@waveshq/standard-defichain-jellyfishsdk": { - "version": "2.23.0", - "resolved": "https://registry.npmjs.org/@waveshq/standard-defichain-jellyfishsdk/-/standard-defichain-jellyfishsdk-2.23.0.tgz", - "integrity": "sha512-2hISndIRcBDTgBBCRgNprIdFXozujcnYZRP1UJGL5jBJO4u5EgJjbv6r/PJhIin/eRuDatK9rUrE8e7T0I7obA==", - "dependencies": { - "@defichain/jellyfish-address": "4.0.0-beta.14.1", - "@defichain/jellyfish-api-core": "4.0.0-beta.14.1", - "@defichain/jellyfish-network": "4.0.0-beta.14.1", - "@defichain/jellyfish-testing": "4.0.0-beta.14.1", - "@defichain/jellyfish-transaction": "4.0.0-beta.14.1", - "@defichain/jellyfish-transaction-builder": "4.0.0-beta.14.1", - "@defichain/jellyfish-wallet": "4.0.0-beta.14.1", - "@defichain/jellyfish-wallet-encrypted": "4.0.0-beta.14.1", - "@defichain/jellyfish-wallet-mnemonic": "4.0.0-beta.14.1", - "@defichain/playground-api-client": "4.0.0-beta.14.1", - "@defichain/testcontainers": "4.0.0-beta.14.1", - "@defichain/whale-api-client": "4.0.0-beta.14.1", - "@defichain/whale-api-wallet": "4.0.0-beta.14.1", - "defichain": "4.0.0-beta.14.1" - } - }, - "node_modules/@waveshq/standard-web": { - "version": "2.23.0", - "resolved": "https://registry.npmjs.org/@waveshq/standard-web/-/standard-web-2.23.0.tgz", - "integrity": "sha512-iSMhZljWZza6F/Ucrw7thWKzOFTQ0vimBQNhr1YyvR5HktyE5Nr0NKZh/TrOvA26QhMF1s1KZStLJkGcwL1Amg==", - "dependencies": { - "@netlify/ipx": "^1.4.5", - "@reduxjs/toolkit": "^1.9.7", - "@tanstack/react-query": "^5.4.3", - "@types/react": "18.2.33", - "@types/react-dom": "18.2.14", - "follow-redirects": "^1.15.3", - "next": "14.0.1", - "next-sitemap": "^4.2.3", - "nextjs-progressbar": "^0.0.16", - "react": "18.2.0", - "react-dom": "18.2.0", - "react-icons": "^4.11.0", - "react-redux": "^8.1.3", - "react-responsive": "^9.0.2", - "typescript": "*" - } - }, - "node_modules/@waveshq/standard-web-linter": { - "version": "2.23.0", - "resolved": "https://registry.npmjs.org/@waveshq/standard-web-linter/-/standard-web-linter-2.23.0.tgz", - "integrity": "sha512-6rUqGRWwWSIpOXsy24zbC3R3ZpuY+llyrf0vd+QT3QeDhTzOywL3dJL2PDNl+5XFXggt0bipn58sNMeI8zkkdw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@waveshq/standard-defichain-jellyfishsdk/-/standard-defichain-jellyfishsdk-4.0.1.tgz", + "integrity": "sha512-Gfl98z/BprvwXniGtrdYRCK5wW1EUcx9J6mLnb/leCOz9Kw8S0LhwHgAF+9y4upNV1QGRuMKvqOAuE/zxTrN5Q==", + "dev": true, + "dependencies": { + "@defichain/jellyfish-address": "4.0.7", + "@defichain/jellyfish-api-core": "4.0.7", + "@defichain/jellyfish-network": "4.0.7", + "@defichain/jellyfish-testing": "4.0.7", + "@defichain/jellyfish-transaction": "4.0.7", + "@defichain/jellyfish-transaction-builder": "4.0.7", + "@defichain/jellyfish-wallet": "4.0.7", + "@defichain/jellyfish-wallet-encrypted": "4.0.7", + "@defichain/jellyfish-wallet-mnemonic": "4.0.7", + "@defichain/playground-api-client": "4.0.7", + "@defichain/testcontainers": "4.0.7", + "@defichain/whale-api-client": "4.0.7", + "@defichain/whale-api-wallet": "4.0.7", + "defichain": "4.0.7" + } + }, + "node_modules/@waveshq/standard-prettier": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@waveshq/standard-prettier/-/standard-prettier-4.0.1.tgz", + "integrity": "sha512-L1rYcZ5x8U8FF2kyEqIqND6cgdS3e8w8t8AZnn9g942VMi6uAlLTGtkuqr+5h2N5YFexRVTz4fE6RtQiIOCAZg==", + "dev": true, "dependencies": { - "eslint": "^8.52.0", + "eslint": "^8.53.0", "eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb-typescript": "^17.1.0", - "eslint-config-next": "14.0.1", "eslint-config-prettier": "^9.0.0", - "eslint-plugin-cypress": "^2.15.1", - "eslint-plugin-import": "^2.29.0", - "eslint-plugin-jsx-a11y": "^6.7.1", - "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^5.0.1", - "eslint-plugin-react": "^7.33.2", - "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-simple-import-sort": "^10.0.0", "husky": "^8.0.3", - "lint-staged": "^15.0.2", - "next": "14.0.1", - "prettier": "^3.0.3", - "typescript": "^5.2.2" + "lint-staged": "^15.1.0", + "prettier": "^3.1.0", + "typescript": "*" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/ansi-escapes": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz", - "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==", + "node_modules/@waveshq/standard-prettier/node_modules/ansi-escapes": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", + "dev": true, + "license": "MIT", "dependencies": { - "type-fest": "^3.0.0" + "environment": "^1.0.0" }, "engines": { - "node": ">=14.16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "node_modules/@waveshq/standard-prettier/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -10228,10 +10489,12 @@ "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/ansi-styles": { + "node_modules/@waveshq/standard-prettier/node_modules/ansi-styles": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -10239,10 +10502,12 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/chalk": { + "node_modules/@waveshq/standard-prettier/node_modules/chalk": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, @@ -10250,24 +10515,28 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "node_modules/@waveshq/standard-prettier/node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "license": "MIT", "dependencies": { - "restore-cursor": "^4.0.0" + "restore-cursor": "^5.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/cli-truncate": { + "node_modules/@waveshq/standard-prettier/node_modules/cli-truncate": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, + "license": "MIT", "dependencies": { "slice-ansi": "^5.0.0", "string-width": "^7.0.0" @@ -10279,23 +10548,47 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/commander": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", - "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "node_modules/@waveshq/standard-prettier/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=16" + "node": ">=18" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/emoji-regex": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", - "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==" + "node_modules/@waveshq/standard-prettier/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } }, - "node_modules/@waveshq/standard-web-linter/node_modules/execa": { + "node_modules/@waveshq/standard-prettier/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@waveshq/standard-prettier/node_modules/execa": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "license": "MIT", "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", @@ -10314,10 +10607,12 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/get-stream": { + "node_modules/@waveshq/standard-prettier/node_modules/get-stream": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "license": "MIT", "engines": { "node": ">=16" }, @@ -10325,18 +10620,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/human-signals": { + "node_modules/@waveshq/standard-prettier/node_modules/human-signals": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=16.17.0" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/is-fullwidth-code-point": { + "node_modules/@waveshq/standard-prettier/node_modules/is-fullwidth-code-point": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -10344,10 +10643,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/is-stream": { + "node_modules/@waveshq/standard-prettier/node_modules/is-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -10355,29 +10656,36 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/lilconfig": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", - "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", + "node_modules/@waveshq/standard-prettier/node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "dev": true, + "license": "MIT", "engines": { "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/lint-staged": { - "version": "15.2.2", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.2.tgz", - "integrity": "sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==", + "node_modules/@waveshq/standard-prettier/node_modules/lint-staged": { + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.10.tgz", + "integrity": "sha512-5dY5t743e1byO19P9I4b3x8HJwalIznL5E1FWYnU6OWw33KxNBSLAc6Cy7F2PsFEO8FKnLwjwm5hx7aMF0jzZg==", + "dev": true, + "license": "MIT", "dependencies": { - "chalk": "5.3.0", - "commander": "11.1.0", - "debug": "4.3.4", - "execa": "8.0.1", - "lilconfig": "3.0.0", - "listr2": "8.0.1", - "micromatch": "4.0.5", - "pidtree": "0.6.0", - "string-argv": "0.3.2", - "yaml": "2.3.4" + "chalk": "~5.3.0", + "commander": "~12.1.0", + "debug": "~4.3.6", + "execa": "~8.0.1", + "lilconfig": "~3.1.2", + "listr2": "~8.2.4", + "micromatch": "~4.0.8", + "pidtree": "~0.6.0", + "string-argv": "~0.3.2", + "yaml": "~2.5.0" }, "bin": { "lint-staged": "bin/lint-staged.js" @@ -10389,30 +10697,34 @@ "url": "https://opencollective.com/lint-staged" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/listr2": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.0.1.tgz", - "integrity": "sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==", + "node_modules/@waveshq/standard-prettier/node_modules/listr2": { + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", + "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", + "dev": true, + "license": "MIT", "dependencies": { "cli-truncate": "^4.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", - "log-update": "^6.0.0", - "rfdc": "^1.3.0", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", "wrap-ansi": "^9.0.0" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/log-update": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", - "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", + "node_modules/@waveshq/standard-prettier/node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "dev": true, + "license": "MIT", "dependencies": { - "ansi-escapes": "^6.2.0", - "cli-cursor": "^4.0.0", - "slice-ansi": "^7.0.0", + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" }, @@ -10423,10 +10735,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/log-update/node_modules/is-fullwidth-code-point": { + "node_modules/@waveshq/standard-prettier/node_modules/log-update/node_modules/is-fullwidth-code-point": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "dev": true, + "license": "MIT", "dependencies": { "get-east-asian-width": "^1.0.0" }, @@ -10437,10 +10751,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/log-update/node_modules/slice-ansi": { + "node_modules/@waveshq/standard-prettier/node_modules/log-update/node_modules/slice-ansi": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" @@ -10452,10 +10768,26 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/mimic-fn": { + "node_modules/@waveshq/standard-prettier/node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/@waveshq/standard-prettier/node_modules/mimic-fn": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -10463,10 +10795,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/npm-run-path": { + "node_modules/@waveshq/standard-prettier/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@waveshq/standard-prettier/node_modules/npm-run-path": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "license": "MIT", "dependencies": { "path-key": "^4.0.0" }, @@ -10477,10 +10818,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/onetime": { + "node_modules/@waveshq/standard-prettier/node_modules/onetime": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "license": "MIT", "dependencies": { "mimic-fn": "^4.0.0" }, @@ -10491,10 +10834,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/path-key": { + "node_modules/@waveshq/standard-prettier/node_modules/path-key": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -10502,52 +10847,58 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, + "node_modules/@waveshq/standard-prettier/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=8.6" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/restore-cursor/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "node_modules/@waveshq/standard-prettier/node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, "engines": { - "node": ">=6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/restore-cursor/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/@waveshq/standard-prettier/node_modules/restore-cursor/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "license": "MIT", "dependencies": { - "mimic-fn": "^2.1.0" + "mimic-function": "^5.0.0" }, "engines": { - "node": ">=6" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/restore-cursor/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "node_modules/@waveshq/standard-web-linter/node_modules/signal-exit": { + "node_modules/@waveshq/standard-prettier/node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", "engines": { "node": ">=14" }, @@ -10555,10 +10906,12 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/slice-ansi": { + "node_modules/@waveshq/standard-prettier/node_modules/slice-ansi": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^6.0.0", "is-fullwidth-code-point": "^4.0.0" @@ -10570,10 +10923,12 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/string-width": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", - "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "node_modules/@waveshq/standard-prettier/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", @@ -10586,10 +10941,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/strip-ansi": { + "node_modules/@waveshq/standard-prettier/node_modules/strip-ansi": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -10600,10 +10957,12 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/strip-final-newline": { + "node_modules/@waveshq/standard-prettier/node_modules/strip-final-newline": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -10611,21 +10970,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/type-fest": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", - "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@waveshq/standard-web-linter/node_modules/wrap-ansi": { + "node_modules/@waveshq/standard-prettier/node_modules/wrap-ansi": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", @@ -10638,7 +10988,502 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/@waveshq/standard-web-linter/node_modules/yaml": { + "node_modules/@waveshq/standard-prettier/node_modules/yaml": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@waveshq/standard-web": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@waveshq/standard-web/-/standard-web-4.0.1.tgz", + "integrity": "sha512-3nacDHfy5sJ5Xd8OPly0SAW8LIlNoozkjjiblmDmz+SwJsAlPQ6VpXzWldu4e/PDwainG+yZKJ02YfrLPX8MXw==", + "dependencies": { + "@netlify/ipx": "^1.4.5", + "@reduxjs/toolkit": "^1.9.7", + "@tanstack/react-query": "^5.8.3", + "@types/react": "18.2.37", + "@types/react-dom": "18.2.15", + "follow-redirects": "^1.15.3", + "next": "14.1.4", + "next-sitemap": "^4.2.3", + "nextjs-progressbar": "^0.0.16", + "react": "18.2.0", + "react-dom": "18.2.0", + "react-icons": "^4.11.0", + "react-redux": "^8.1.3", + "react-responsive": "^9.0.2", + "typescript": "*" + } + }, + "node_modules/@waveshq/standard-web-linter": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@waveshq/standard-web-linter/-/standard-web-linter-4.0.1.tgz", + "integrity": "sha512-uEULA1VvJE4nE/ZvJcvDh1n8o2PVwXN7fA6pKZEyZOaLR1foyCihBsvSud8DPFsLFb801BQO3VE2HTWRquh2PA==", + "dependencies": { + "eslint": "^8.53.0", + "eslint-config-airbnb": "^19.0.4", + "eslint-config-airbnb-typescript": "^17.1.0", + "eslint-config-next": "14.0.2", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-cypress": "^2.15.1", + "eslint-plugin-import": "^2.29.0", + "eslint-plugin-jsx-a11y": "^6.8.0", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-prettier": "^5.0.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-simple-import-sort": "^10.0.0", + "husky": "^8.0.3", + "lint-staged": "^15.1.0", + "next": "14.1.4", + "prettier": "^3.1.0", + "typescript": "^5.2.2" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/ansi-escapes": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz", + "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==", + "dependencies": { + "type-fest": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "dependencies": { + "restore-cursor": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "engines": { + "node": ">=16" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==" + }, + "node_modules/@waveshq/standard-web-linter/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/lilconfig": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", + "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", + "engines": { + "node": ">=14" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/lint-staged": { + "version": "15.2.2", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.2.tgz", + "integrity": "sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==", + "dependencies": { + "chalk": "5.3.0", + "commander": "11.1.0", + "debug": "4.3.4", + "execa": "8.0.1", + "lilconfig": "3.0.0", + "listr2": "8.0.1", + "micromatch": "4.0.5", + "pidtree": "0.6.0", + "string-argv": "0.3.2", + "yaml": "2.3.4" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/listr2": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.0.1.tgz", + "integrity": "sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==", + "dependencies": { + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.0.0", + "rfdc": "^1.3.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/log-update": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", + "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", + "dependencies": { + "ansi-escapes": "^6.2.0", + "cli-cursor": "^4.0.0", + "slice-ansi": "^7.0.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "dependencies": { + "get-east-asian-width": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/restore-cursor/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/restore-cursor/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/restore-cursor/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/@waveshq/standard-web-linter/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/type-fest": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@waveshq/standard-web-linter/node_modules/yaml": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", @@ -10647,41 +11492,16 @@ } }, "node_modules/@waveshq/standard-web/node_modules/@types/react": { - "version": "18.2.33", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.33.tgz", - "integrity": "sha512-v+I7S+hu3PIBoVkKGpSYYpiBT1ijqEzWpzQD62/jm4K74hPpSP7FF9BnKG6+fg2+62weJYkkBWDJlZt5JO/9hg==", + "version": "18.2.37", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.37.tgz", + "integrity": "sha512-RGAYMi2bhRgEXT3f4B92WTohopH6bIXw05FuGlmJEnv/omEn190+QYEIYxIAuIBdKgboYYdVved2p1AxZVQnaw==", + "license": "MIT", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", "csstype": "^3.0.2" } }, - "node_modules/@waveshq/walletkit-core": { - "version": "1.3.10", - "resolved": "https://registry.npmjs.org/@waveshq/walletkit-core/-/walletkit-core-1.3.10.tgz", - "integrity": "sha512-bK8fV9v+8m7W0cbN9fFesi3wiOff+ev6y9LzQFhSiH0pcm8Bnk7kb4DL3paqL9tqUi6nw8RbFbYloLYLEuMuRg==", - "dependencies": { - "bignumber.js": "^9.1.2", - "ethers": "^5.7.2" - } - }, - "node_modules/@waveshq/walletkit-ui": { - "version": "1.3.10", - "resolved": "https://registry.npmjs.org/@waveshq/walletkit-ui/-/walletkit-ui-1.3.10.tgz", - "integrity": "sha512-4Hwm6BQAcYqeApHlSmAWpNoHq+M15BVeijkQpgw3nKpqQ/wyNEtl6I/MdBHqYPRcJkZjDGSg1M1HZxnuyqvpRA==", - "dependencies": { - "@stickyjs/jest": "^1.3.2", - "@waveshq/standard-defichain-jellyfishsdk": "^2.14.0", - "@waveshq/standard-web": "^2.14.0", - "@waveshq/standard-web-linter": "^2.14.0", - "@waveshq/walletkit-core": "1.3.10", - "bignumber.js": "^9.1.2", - "dayjs": "^1.11.10", - "immer": "^9.0.21", - "reselect": "^4.1.8", - "smart-buffer": "^4.2.0" - } - }, "node_modules/@webassemblyjs/ast": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", @@ -11243,26 +12063,256 @@ "node": ">=4" } }, - "node_modules/any-base": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", - "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==", - "dev": true - }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "node_modules/anti-trojan-source": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/anti-trojan-source/-/anti-trojan-source-1.4.1.tgz", + "integrity": "sha512-DruSp30RgiEW36/n5+e2RtJf2W57jBS01YHvH8SL1vSFIpIeArfreTCxelHPMEhGLpk/BZUeA3uWt5AeTCHq9g==", + "license": "Apache-2.0", "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "globby": "^12.0.2", + "meow": "^10.1.1" }, - "engines": { + "bin": { + "anti-trojan-source": "bin/anti-trojan-source.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/anti-trojan-source/node_modules/array-union": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", + "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/anti-trojan-source/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/anti-trojan-source/node_modules/camelcase-keys": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-7.0.2.tgz", + "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==", + "license": "MIT", + "dependencies": { + "camelcase": "^6.3.0", + "map-obj": "^4.1.0", + "quick-lru": "^5.1.1", + "type-fest": "^1.2.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/anti-trojan-source/node_modules/decamelize": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.1.tgz", + "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/anti-trojan-source/node_modules/globby": { + "version": "12.2.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz", + "integrity": "sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==", + "license": "MIT", + "dependencies": { + "array-union": "^3.0.1", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.7", + "ignore": "^5.1.9", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/anti-trojan-source/node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/anti-trojan-source/node_modules/meow": { + "version": "10.1.5", + "resolved": "https://registry.npmjs.org/meow/-/meow-10.1.5.tgz", + "integrity": "sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==", + "license": "MIT", + "dependencies": { + "@types/minimist": "^1.2.2", + "camelcase-keys": "^7.0.0", + "decamelize": "^5.0.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.2", + "read-pkg-up": "^8.0.0", + "redent": "^4.0.0", + "trim-newlines": "^4.0.2", + "type-fest": "^1.2.2", + "yargs-parser": "^20.2.9" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/anti-trojan-source/node_modules/read-pkg": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-6.0.0.tgz", + "integrity": "sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==", + "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^3.0.2", + "parse-json": "^5.2.0", + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/anti-trojan-source/node_modules/read-pkg-up": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-8.0.0.tgz", + "integrity": "sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==", + "license": "MIT", + "dependencies": { + "find-up": "^5.0.0", + "read-pkg": "^6.0.0", + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/anti-trojan-source/node_modules/redent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-4.0.0.tgz", + "integrity": "sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==", + "license": "MIT", + "dependencies": { + "indent-string": "^5.0.0", + "strip-indent": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/anti-trojan-source/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/anti-trojan-source/node_modules/strip-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", + "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/anti-trojan-source/node_modules/trim-newlines": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.1.1.tgz", + "integrity": "sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/anti-trojan-source/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/any-base": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", + "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==", + "dev": true + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { "node": ">= 8" } }, @@ -11821,36 +12871,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/babel-eslint": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", - "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==", - "deprecated": "babel-eslint is now @babel/eslint-parser. This package will no longer receive updates.", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.7.0", - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0", - "eslint-visitor-keys": "^1.0.0", - "resolve": "^1.12.0" - }, - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "eslint": ">= 4.12.1" - } - }, - "node_modules/babel-eslint/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -12265,9 +13285,11 @@ } }, "node_modules/base-x": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.10.tgz", + "integrity": "sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ==", + "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "^5.0.1" } @@ -12302,7 +13324,9 @@ "node_modules/bech32": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", - "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==" + "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==", + "dev": true, + "license": "MIT" }, "node_modules/better-opn": { "version": "3.0.2", @@ -12343,6 +13367,8 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "license": "MIT", "dependencies": { "file-uri-to-path": "1.0.0" } @@ -12351,6 +13377,8 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/bip32/-/bip32-2.0.6.tgz", "integrity": "sha512-HpV5OMLLGTjSVblmrtYRfFFKuQB+GArM0+XP8HGWfJ5vxYBqo+DesvJwOdC2WJ3bCkZShGf0QIfoIpeomVzVdA==", + "dev": true, + "license": "MIT", "dependencies": { "@types/node": "10.12.18", "bs58check": "^2.1.1", @@ -12367,12 +13395,16 @@ "node_modules/bip32/node_modules/@types/node": { "version": "10.12.18", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", - "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==" + "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==", + "dev": true, + "license": "MIT" }, "node_modules/bip39": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.1.0.tgz", "integrity": "sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==", + "dev": true, + "license": "ISC", "dependencies": { "@noble/hashes": "^1.2.0" } @@ -12381,6 +13413,8 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", "integrity": "sha512-nemMHz95EmS38a26XbbdxIYj5csHd3RMP3H5bwQknX0WYHF01qhpufP42mLOwVICuH2JmhIhXiWs89MfUGL7Xw==", + "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "^5.0.1" } @@ -12550,11 +13584,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -12569,6 +13604,8 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "license": "MIT", "dependencies": { "buffer-xor": "^1.0.3", "cipher-base": "^1.0.0", @@ -12624,6 +13661,8 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "dev": true, + "license": "MIT", "dependencies": { "base-x": "^3.0.2" } @@ -12632,6 +13671,8 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "dev": true, + "license": "MIT", "dependencies": { "bs58": "^4.0.0", "create-hash": "^1.1.0", @@ -12713,7 +13754,9 @@ "node_modules/buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==" + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", + "dev": true, + "license": "MIT" }, "node_modules/buildcheck": { "version": "0.0.6", @@ -13085,12 +14128,6 @@ "node": ">=10" } }, - "node_modules/chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, "node_modules/charenc": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", @@ -13233,6 +14270,8 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -13325,20 +14364,26 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-width": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" }, + "node_modules/clipanion": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/clipanion/-/clipanion-3.2.1.tgz", + "integrity": "sha512-dYFdjLb7y1ajfxQopN05mylEpK9ZX0sO1/RfMXdfmwjlIsPkbh4p7A682x++zFPLDCo1x3p82dtljHf5cW2LKA==", + "license": "MIT", + "workspaces": [ + "website" + ], + "dependencies": { + "typanion": "^3.8.0" + }, + "peerDependencies": { + "typanion": "*" + } + }, "node_modules/clipboardy": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-4.0.0.tgz", @@ -14284,6 +15329,8 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "license": "MIT", "dependencies": { "cipher-base": "^1.0.1", "inherits": "^2.0.1", @@ -14296,6 +15343,8 @@ "version": "1.1.7", "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "license": "MIT", "dependencies": { "cipher-base": "^1.0.3", "create-hash": "^1.1.0", @@ -14538,6 +15587,13 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true, + "license": "MIT" + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -15170,9 +16226,17 @@ } }, "node_modules/defichain": { - "version": "4.0.0-beta.14.1", - "resolved": "https://registry.npmjs.org/defichain/-/defichain-4.0.0-beta.14.1.tgz", - "integrity": "sha512-OUi91flnir9B9i4YEtSnBPlIB+n0whoxA1cjZc0S8c2ZvNtc/YznxgsaDnBe5UrbKhNtiblmveq9EjLHsI2cvA==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/defichain/-/defichain-4.0.7.tgz", + "integrity": "sha512-bnXlw7UH8oskLVCb4ab4klNrxXZKWwBYvCmJdK35Owa1TlLANIfBDEAPQXfL07ybZZxu8sCVECz1U0Vjup/o9Q==", + "dev": true, + "license": "MIT", + "workspaces": [ + "./", + "./apps", + "./website", + "./packages/*" + ], "engines": { "node": ">=v16.17.0" } @@ -15874,6 +16938,19 @@ "node": ">=4" } }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/eol": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/eol/-/eol-0.9.1.tgz", @@ -16239,424 +17316,13 @@ "eslint-plugin-import": "^2.25.3" } }, - "node_modules/eslint-config-esnext": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-esnext/-/eslint-config-esnext-4.1.0.tgz", - "integrity": "sha512-GhfVEXdqYKEIIj7j+Fw2SQdL9qyZMekgXfq6PyXM66cQw0B435ddjz3P3kxOBVihMRJ0xGYjosaveQz5Y6z0uA==", - "dev": true, - "dependencies": { - "babel-eslint": "^10.0.1", - "eslint": "^6.8.0", - "eslint-plugin-babel": "^5.2.1", - "eslint-plugin-import": "^2.14.0" - }, - "peerDependencies": { - "eslint": "^6.0.0" - } - }, - "node_modules/eslint-config-esnext/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/eslint-config-esnext/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/eslint-config-esnext/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/eslint-config-esnext/node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/eslint-config-esnext/node_modules/cross-spawn/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/eslint-config-esnext/node_modules/eslint": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", - "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "ajv": "^6.10.0", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "eslint-scope": "^5.0.0", - "eslint-utils": "^1.4.3", - "eslint-visitor-keys": "^1.1.0", - "espree": "^6.1.2", - "esquery": "^1.0.1", - "esutils": "^2.0.2", - "file-entry-cache": "^5.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "inquirer": "^7.0.0", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.14", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.3", - "progress": "^2.0.0", - "regexpp": "^2.0.1", - "semver": "^6.1.2", - "strip-ansi": "^5.2.0", - "strip-json-comments": "^3.0.1", - "table": "^5.2.3", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-esnext/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-config-esnext/node_modules/eslint-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", - "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/eslint-config-esnext/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-config-esnext/node_modules/espree": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", - "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", - "dev": true, - "dependencies": { - "acorn": "^7.1.1", - "acorn-jsx": "^5.2.0", - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/eslint-config-esnext/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint-config-esnext/node_modules/file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", - "dev": true, - "dependencies": { - "flat-cache": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-config-esnext/node_modules/flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", - "dev": true, - "dependencies": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-config-esnext/node_modules/flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", - "dev": true - }, - "node_modules/eslint-config-esnext/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/eslint-config-esnext/node_modules/globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dev": true, - "dependencies": { - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint-config-esnext/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/eslint-config-esnext/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/eslint-config-esnext/node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/eslint-config-esnext/node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/eslint-config-esnext/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-config-esnext/node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/eslint-config-esnext/node_modules/regexpp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", - "dev": true, - "engines": { - "node": ">=6.5.0" - } - }, - "node_modules/eslint-config-esnext/node_modules/rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/eslint-config-esnext/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-config-esnext/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "dev": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-config-esnext/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-config-esnext/node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "node_modules/eslint-config-esnext/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/eslint-config-esnext/node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/eslint-config-esnext/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint-config-esnext/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, "node_modules/eslint-config-next": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.0.1.tgz", - "integrity": "sha512-QfIFK2WD39H4WOespjgf6PLv9Bpsd7KGGelCtmq4l67nGvnlsGpuvj0hIT+aIy6p5gKH+lAChYILsyDlxP52yg==", + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.0.2.tgz", + "integrity": "sha512-CasWThlsyIcg/a+clU6KVOMTieuDhTztsrqvniP6AsRki9v7FnojTa7vKQOYM8QSOsQdZ/aElLD1Y2Oc8/PsIg==", + "license": "MIT", "dependencies": { - "@next/eslint-plugin-next": "14.0.1", + "@next/eslint-plugin-next": "14.0.2", "@rushstack/eslint-patch": "^1.3.3", "@typescript-eslint/parser": "^5.4.2 || ^6.0.0", "eslint-import-resolver-node": "^0.3.6", @@ -16676,416 +17342,6 @@ } } }, - "node_modules/eslint-config-node": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-node/-/eslint-config-node-4.1.0.tgz", - "integrity": "sha512-Wz17xV5O2WFG8fGdMYEBdbiL6TL7YNJSJvSX9V4sXQownewfYmoqlly7wxqLkOUv/57pq6LnnotMiQQrrPjCqQ==", - "dev": true, - "dependencies": { - "eslint": "^6.8.0", - "eslint-config-esnext": "^4.1.0" - }, - "peerDependencies": { - "eslint": "^6.0.0" - } - }, - "node_modules/eslint-config-node/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/eslint-config-node/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/eslint-config-node/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/eslint-config-node/node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/eslint-config-node/node_modules/cross-spawn/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/eslint-config-node/node_modules/eslint": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", - "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "ajv": "^6.10.0", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "eslint-scope": "^5.0.0", - "eslint-utils": "^1.4.3", - "eslint-visitor-keys": "^1.1.0", - "espree": "^6.1.2", - "esquery": "^1.0.1", - "esutils": "^2.0.2", - "file-entry-cache": "^5.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "inquirer": "^7.0.0", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.14", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.3", - "progress": "^2.0.0", - "regexpp": "^2.0.1", - "semver": "^6.1.2", - "strip-ansi": "^5.2.0", - "strip-json-comments": "^3.0.1", - "table": "^5.2.3", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-node/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-config-node/node_modules/eslint-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", - "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/eslint-config-node/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-config-node/node_modules/espree": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", - "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", - "dev": true, - "dependencies": { - "acorn": "^7.1.1", - "acorn-jsx": "^5.2.0", - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/eslint-config-node/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint-config-node/node_modules/file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", - "dev": true, - "dependencies": { - "flat-cache": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-config-node/node_modules/flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", - "dev": true, - "dependencies": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-config-node/node_modules/flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", - "dev": true - }, - "node_modules/eslint-config-node/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/eslint-config-node/node_modules/globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dev": true, - "dependencies": { - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint-config-node/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/eslint-config-node/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/eslint-config-node/node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/eslint-config-node/node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/eslint-config-node/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-config-node/node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/eslint-config-node/node_modules/regexpp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", - "dev": true, - "engines": { - "node": ">=6.5.0" - } - }, - "node_modules/eslint-config-node/node_modules/rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/eslint-config-node/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-config-node/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "dev": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-config-node/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-config-node/node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "node_modules/eslint-config-node/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/eslint-config-node/node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/eslint-config-node/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint-config-node/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, "node_modules/eslint-config-prettier": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", @@ -17116,16 +17372,18 @@ } }, "node_modules/eslint-import-resolver-typescript": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", - "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.3.tgz", + "integrity": "sha512-ud9aw4szY9cCT1EWWdGv1L1XR6hh2PaRWif0j2QjQ0pgTY/69iw+W0Z4qZv5wHahOl8isEr+k/JnyAqNQkLkIA==", + "license": "ISC", "dependencies": { - "debug": "^4.3.4", - "enhanced-resolve": "^5.12.0", - "eslint-module-utils": "^2.7.4", - "fast-glob": "^3.3.1", - "get-tsconfig": "^4.5.0", - "is-core-module": "^2.11.0", + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.3.5", + "enhanced-resolve": "^5.15.0", + "eslint-module-utils": "^2.8.1", + "fast-glob": "^3.3.2", + "get-tsconfig": "^4.7.5", + "is-bun-module": "^1.0.2", "is-glob": "^4.0.3" }, "engines": { @@ -17136,9 +17394,41 @@ }, "peerDependencies": { "eslint": "*", - "eslint-plugin-import": "*" + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-import-resolver-typescript/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, + "node_modules/eslint-import-resolver-typescript/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, "node_modules/eslint-module-utils": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", @@ -17163,19 +17453,33 @@ "ms": "^2.1.1" } }, - "node_modules/eslint-plugin-babel": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-babel/-/eslint-plugin-babel-5.3.1.tgz", - "integrity": "sha512-VsQEr6NH3dj664+EyxJwO4FCYm/00JhYb3Sk3ft8o+fpKuIfQ9TaW6uVUfvwMXHcf/lsnRIoyFPsLMyiWCSL/g==", - "dev": true, + "node_modules/eslint-plugin-anti-trojan-source": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-anti-trojan-source/-/eslint-plugin-anti-trojan-source-1.1.1.tgz", + "integrity": "sha512-gWDuG2adNNccwRM+2/Q3UHqV1DgrAUSpSi/Tdnx2Ybr0ndWMSBn7lt4AbxdPuFSEs2OAokX/vdIHbBbTLzWspw==", + "license": "Apache-2.0", "dependencies": { - "eslint-rule-composer": "^0.3.0" + "anti-trojan-source": "^1.3.1" + } + }, + "node_modules/eslint-plugin-check-file": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-check-file/-/eslint-plugin-check-file-2.8.0.tgz", + "integrity": "sha512-FvvafMTam2WJYH9uj+FuMxQ1y+7jY3Z6P9T4j2214cH0FBxNzTcmeCiGTj1Lxp3mI6kbbgsXvmgewvf+llKYyw==", + "license": "Apache-2.0", + "dependencies": { + "is-glob": "^4.0.3", + "micromatch": "^4.0.5" }, "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "type": "ko_fi", + "url": "https://ko-fi.com/huanluo" }, "peerDependencies": { - "eslint": ">=4.0.0" + "eslint": ">=7.28.0" } }, "node_modules/eslint-plugin-cypress": { @@ -17289,153 +17593,6 @@ "semver": "bin/semver.js" } }, - "node_modules/eslint-plugin-jest": { - "version": "27.4.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.4.3.tgz", - "integrity": "sha512-7S6SmmsHsgIm06BAGCAxL+ABd9/IB3MWkz2pudj6Qqor2y1qQpWPfuFU4SG9pWj4xDjF0e+D7Llh5useuSzAZw==", - "dev": true, - "dependencies": { - "@typescript-eslint/utils": "^5.10.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0", - "eslint": "^7.0.0 || ^8.0.0", - "jest": "*" - }, - "peerDependenciesMeta": { - "@typescript-eslint/eslint-plugin": { - "optional": true - }, - "jest": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/eslint-plugin-jest/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-plugin-jest/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/eslint-plugin-jsx-a11y": { "version": "6.8.0", "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz", @@ -17473,6 +17630,15 @@ "dequal": "^2.0.3" } }, + "node_modules/eslint-plugin-no-only-tests": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-no-only-tests/-/eslint-plugin-no-only-tests-3.3.0.tgz", + "integrity": "sha512-brcKcxGnISN2CcVhXJ/kEQlNa0MEfGRtwKtWA16SkqXHKitaKIMrfemJKLKX1YqDU5C/5JY3PvZXd5jEW04e0Q==", + "license": "MIT", + "engines": { + "node": ">=5.0.0" + } + }, "node_modules/eslint-plugin-node": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", @@ -17571,24 +17737,6 @@ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" } }, - "node_modules/eslint-plugin-react-native": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-native/-/eslint-plugin-react-native-4.1.0.tgz", - "integrity": "sha512-QLo7rzTBOl43FvVqDdq5Ql9IoElIuTdjrz9SKAXCvULvBoRZ44JGSkx9z4999ZusCsb4rK3gjS8gOGyeYqZv2Q==", - "dev": true, - "dependencies": { - "eslint-plugin-react-native-globals": "^0.1.1" - }, - "peerDependencies": { - "eslint": "^3.17.0 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-react-native-globals": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-native-globals/-/eslint-plugin-react-native-globals-0.1.2.tgz", - "integrity": "sha512-9aEPf1JEpiTjcFAmmyw8eiIXmcNZOqaZyHO77wgm0/dWfT/oxC1SrIq8ET38pMxHYrcB6Uew+TzUVsBeczF88g==", - "dev": true - }, "node_modules/eslint-plugin-react/node_modules/doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -17632,11 +17780,31 @@ "eslint": ">=5.0.0" } }, + "node_modules/eslint-plugin-unused-imports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-3.2.0.tgz", + "integrity": "sha512-6uXyn6xdINEpxE1MtDjxQsyXB37lfyO2yKGVVgtD7WEWQGORSOZjgrD6hBhvGv4/SO+TOlS+UnC6JppRqbuwGQ==", + "license": "MIT", + "dependencies": { + "eslint-rule-composer": "^0.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "6 - 7", + "eslint": "8" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + } + } + }, "node_modules/eslint-rule-composer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz", "integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==", - "dev": true, "engines": { "node": ">=4.0.0" } @@ -17932,6 +18100,8 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "license": "MIT", "dependencies": { "md5.js": "^1.3.4", "safe-buffer": "^5.1.1" @@ -18457,44 +18627,6 @@ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true }, - "node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, - "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/external-editor/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/external-editor/node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, "node_modules/extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", @@ -18708,7 +18840,9 @@ "node_modules/file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "license": "MIT" }, "node_modules/filesize": { "version": "8.0.7", @@ -18720,9 +18854,10 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -19226,12 +19361,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", - "dev": true - }, "node_modules/functions-have-names": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", @@ -19408,9 +19537,10 @@ } }, "node_modules/get-tsconfig": { - "version": "4.7.3", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.3.tgz", - "integrity": "sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", + "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", + "license": "MIT", "dependencies": { "resolve-pkg-maps": "^1.0.0" }, @@ -19563,7 +19693,9 @@ "node_modules/glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true, + "peer": true }, "node_modules/global": { "version": "4.4.0", @@ -19887,6 +20019,8 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.4", "readable-stream": "^3.6.0", @@ -20415,118 +20549,6 @@ "fast-loops": "^1.1.3" } }, - "node_modules/inquirer": { - "version": "7.3.3", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", - "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.19", - "mute-stream": "0.0.8", - "run-async": "^2.4.0", - "rxjs": "^6.6.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/inquirer/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/inquirer/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/inquirer/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/inquirer/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/inquirer/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/inquirer/node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/inquirer/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/inquirer/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, "node_modules/install": { "version": "0.13.0", "resolved": "https://registry.npmjs.org/install/-/install-0.13.0.tgz", @@ -20734,6 +20756,15 @@ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, + "node_modules/is-bun-module": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.2.1.tgz", + "integrity": "sha512-AmidtEM6D6NmUiLOvvU7+IePxjEjOzra2h0pSrsfSAcXwl/83zLLXDByafUJy9k/rKK0pvXMLdwKwGHlX2Ke6Q==", + "license": "MIT", + "dependencies": { + "semver": "^7.6.3" + } + }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", @@ -21002,6 +21033,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -24020,7 +24052,9 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz", "integrity": "sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==", + "dev": true, "hasInstallScript": true, + "license": "MIT", "dependencies": { "node-addon-api": "^2.0.0", "node-gyp-build": "^4.2.0", @@ -25346,7 +25380,9 @@ "node_modules/lossless-json": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/lossless-json/-/lossless-json-1.0.5.tgz", - "integrity": "sha512-RicKUuLwZVNZ6ZdJHgIZnSeA05p8qWc5NW0uR96mpPIjN9WDLUg9+kj1esQU1GkPn9iLZVKatSQK5gyiaFHgJA==" + "integrity": "sha512-RicKUuLwZVNZ6ZdJHgIZnSeA05p8qWc5NW0uR96mpPIjN9WDLUg9+kj1esQU1GkPn9iLZVKatSQK5gyiaFHgJA==", + "dev": true, + "license": "MIT" }, "node_modules/lowercase-keys": { "version": "2.0.0", @@ -25469,6 +25505,8 @@ "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "license": "MIT", "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1", @@ -26275,6 +26313,19 @@ "node": ">=6" } }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", @@ -26471,12 +26522,6 @@ "resolved": "https://registry.npmjs.org/murmurhash/-/murmurhash-2.0.1.tgz", "integrity": "sha512-5vQEh3y+DG/lMPM0mCGPDnyV8chYg/g7rl6v3Gd8WMF9S429ox3Xk8qrk174kWhG767KQMqqxLD1WnGd77hiew==" }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, "node_modules/mv": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", @@ -26532,7 +26577,8 @@ "node_modules/nan": { "version": "2.19.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.19.0.tgz", - "integrity": "sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==" + "integrity": "sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==", + "devOptional": true }, "node_modules/nanoid": { "version": "3.3.7", @@ -26589,17 +26635,18 @@ "integrity": "sha512-SrQrok4CATudVzBS7coSz26QRSmlK9TzzoFbeKfcPBUFPjcQM9Rqvr/DlJkOrwI/0KcgvMub1n1g5Jt9EgRn4A==" }, "node_modules/next": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/next/-/next-14.0.1.tgz", - "integrity": "sha512-s4YaLpE4b0gmb3ggtmpmV+wt+lPRuGtANzojMQ2+gmBpgX9w5fTbjsy6dXByBuENsdCX5pukZH/GxdFgO62+pA==", + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/next/-/next-14.1.4.tgz", + "integrity": "sha512-1WTaXeSrUwlz/XcnhGTY7+8eiaFvdet5z9u3V2jb+Ek1vFo0VhHKSAIJvDWfQpttWjnyw14kBeq28TPq7bTeEQ==", + "license": "MIT", "dependencies": { - "@next/env": "14.0.1", + "@next/env": "14.1.4", "@swc/helpers": "0.5.2", "busboy": "1.6.0", - "caniuse-lite": "^1.0.30001406", + "caniuse-lite": "^1.0.30001579", + "graceful-fs": "^4.2.11", "postcss": "8.4.31", - "styled-jsx": "5.1.1", - "watchpack": "2.4.0" + "styled-jsx": "5.1.1" }, "bin": { "next": "dist/bin/next" @@ -26608,15 +26655,15 @@ "node": ">=18.17.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "14.0.1", - "@next/swc-darwin-x64": "14.0.1", - "@next/swc-linux-arm64-gnu": "14.0.1", - "@next/swc-linux-arm64-musl": "14.0.1", - "@next/swc-linux-x64-gnu": "14.0.1", - "@next/swc-linux-x64-musl": "14.0.1", - "@next/swc-win32-arm64-msvc": "14.0.1", - "@next/swc-win32-ia32-msvc": "14.0.1", - "@next/swc-win32-x64-msvc": "14.0.1" + "@next/swc-darwin-arm64": "14.1.4", + "@next/swc-darwin-x64": "14.1.4", + "@next/swc-linux-arm64-gnu": "14.1.4", + "@next/swc-linux-arm64-musl": "14.1.4", + "@next/swc-linux-x64-gnu": "14.1.4", + "@next/swc-linux-x64-musl": "14.1.4", + "@next/swc-win32-arm64-msvc": "14.1.4", + "@next/swc-win32-ia32-msvc": "14.1.4", + "@next/swc-win32-x64-msvc": "14.1.4" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", @@ -26737,7 +26784,9 @@ "node_modules/node-addon-api": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", + "dev": true, + "license": "MIT" }, "node_modules/node-dir": { "version": "0.1.17", @@ -26810,9 +26859,11 @@ } }, "node_modules/node-gyp-build": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz", - "integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==", + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.2.tgz", + "integrity": "sha512-IRUxE4BVsHWXkV/SFOut4qTlagw2aM8T5/vnTsmrHJvVoKueJHRc/JaFND7QDDc61kLYUJ6qlZM3sqTSyx2dTw==", + "dev": true, + "license": "MIT", "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", @@ -26857,7 +26908,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, "dependencies": { "hosted-git-info": "^4.0.1", "is-core-module": "^2.5.0", @@ -26872,7 +26922,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -26884,7 +26933,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -28823,6 +28871,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, "dependencies": { "safe-buffer": "^5.1.0" } @@ -29086,6 +29135,23 @@ "react": "^18.2.0" } }, + "node_modules/react-error-boundary": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-3.1.4.tgz", + "integrity": "sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + }, + "peerDependencies": { + "react": ">=16.13.1" + } + }, "node_modules/react-error-overlay": { "version": "6.0.11", "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", @@ -30293,6 +30359,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "license": "MIT", "funding": { "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } @@ -30352,9 +30419,10 @@ } }, "node_modules/rfdc": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", - "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==" + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "license": "MIT" }, "node_modules/rgb-regex": { "version": "1.0.1", @@ -30381,6 +30449,8 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "license": "MIT", "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1" @@ -30408,15 +30478,6 @@ "resolved": "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.1.2.tgz", "integrity": "sha512-PGMBq03+TTG/p/cRB7HCLKJ1MgDIi07+QU1faSjiYRfmY5UsAttV9Hs08jDAHVwcOwmVLcSJkpwyfXszVjWfIQ==" }, - "node_modules/run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -30599,12 +30660,10 @@ "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==" }, "node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -30637,17 +30696,6 @@ "semver": "bin/semver" } }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", @@ -30819,6 +30867,8 @@ "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "license": "(MIT AND BSD-3-Clause)", "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -32533,94 +32583,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/table": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", - "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", - "dev": true, - "dependencies": { - "ajv": "^6.10.2", - "lodash": "^4.17.14", - "slice-ansi": "^2.1.0", - "string-width": "^3.0.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/table/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/table/node_modules/astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/table/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "node_modules/table/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/table/node_modules/slice-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/table/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/table/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/tailwind-rn": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/tailwind-rn/-/tailwind-rn-3.0.1.tgz", @@ -33502,7 +33464,9 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-1.1.6.tgz", "integrity": "sha512-FmqJZGduTyvsr2cF3375fqGHUovSwDi/QytexX1Se4BPuPZpTE5Ftp5fg+EFSuEf3lhZqgCRjEG3ydUQ/aNiwA==", + "dev": true, "hasInstallScript": true, + "license": "MIT", "dependencies": { "bindings": "^1.3.0", "bn.js": "^4.11.8", @@ -33517,7 +33481,9 @@ "node_modules/tiny-secp256k1/node_modules/bn.js": { "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true, + "license": "MIT" }, "node_modules/tinycolor2": { "version": "1.6.0", @@ -33550,6 +33516,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -33775,27 +33742,6 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -33807,11 +33753,122 @@ "node": "*" } }, + "node_modules/turbo": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/turbo/-/turbo-2.1.3.tgz", + "integrity": "sha512-lY0yj2GH2a2a3NExZ3rGe+rHUVeFE2aXuRAue57n+08E7Z7N7YCmynju0kPC1grAQzERmoLpKrmzmWd+PNiADw==", + "license": "MIT", + "peer": true, + "bin": { + "turbo": "bin/turbo" + }, + "optionalDependencies": { + "turbo-darwin-64": "2.1.3", + "turbo-darwin-arm64": "2.1.3", + "turbo-linux-64": "2.1.3", + "turbo-linux-arm64": "2.1.3", + "turbo-windows-64": "2.1.3", + "turbo-windows-arm64": "2.1.3" + } + }, + "node_modules/turbo-darwin-64": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-2.1.3.tgz", + "integrity": "sha512-ouJOm0g0YyoBuhmikEujVCBGo3Zr0lbSOWFIsQtWUTItC88F2w2byhjtsYGPXQwMlTbXwmoBU2lOCfWNkeEwHQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true + }, + "node_modules/turbo-darwin-arm64": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-2.1.3.tgz", + "integrity": "sha512-j2FOJsK4LAOtHQlb3Oom0yWB/Vi0nF1ljInr311mVzHoFAJRZtfW2fRvdZRb/lBUwjSp8be58qWHzANIcrA0OA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true + }, + "node_modules/turbo-linux-64": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-2.1.3.tgz", + "integrity": "sha512-ubRHkI1gSel7H7wsmxKK8C9UlLWqg/2dkCC88LFupaK6TKgvBKqDqA0Z1M9C/escK0Jsle2k0H8bybV9OYIl4Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/turbo-linux-arm64": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-2.1.3.tgz", + "integrity": "sha512-LffUL+e5wv7BtD6DgnM2kKOlDkMo2eRjhbAjVnrCD3wi2ug0tl6NDzajnHHjtaMyOnIf4AvzSKdLWsBxafGBQA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/turbo-windows-64": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-2.1.3.tgz", + "integrity": "sha512-S9SvcZZoaq5jKr6kA6eF7/xgQhVn8Vh7PVy5lono9zybvhyL4eY++y2PaLToIgL8G9IcbLmgOC73ExNjFBg9XQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true + }, + "node_modules/turbo-windows-arm64": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-2.1.3.tgz", + "integrity": "sha512-twlEo8lRrGbrR6T/ZklUIquW3IlFCEtywklgVA81aIrSBm56+GEVpSrHhIlsx1hiYeSNrs+GpDwZGe+V7fvEVQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true + }, "node_modules/tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" }, + "node_modules/typanion": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/typanion/-/typanion-3.14.0.tgz", + "integrity": "sha512-ZW/lVMRabETuYCd9O9ZvMhAh8GslSqaUjxmK/JLPCh6l73CvLBiuXswj/+7LdnWOgYsQ130FqLzFz5aGT4I3Ug==", + "license": "MIT", + "workspaces": [ + "website" + ] + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -33929,7 +33986,9 @@ "node_modules/typeforce": { "version": "1.18.0", "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", - "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==" + "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==", + "dev": true, + "license": "MIT" }, "node_modules/typescript": { "version": "5.4.2", @@ -34396,7 +34455,9 @@ "node_modules/url-search-params-polyfill": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/url-search-params-polyfill/-/url-search-params-polyfill-8.1.1.tgz", - "integrity": "sha512-KmkCs6SjE6t4ihrfW9JelAPQIIIFbJweaaSLTh/4AO+c58JlDcb+GbdPt8yr5lRcFg4rPswRFRRhBGpWwh0K/Q==" + "integrity": "sha512-KmkCs6SjE6t4ihrfW9JelAPQIIIFbJweaaSLTh/4AO+c58JlDcb+GbdPt8yr5lRcFg4rPswRFRRhBGpWwh0K/Q==", + "dev": true, + "license": "MIT" }, "node_modules/url/node_modules/punycode": { "version": "1.4.1", @@ -34464,20 +34525,16 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } }, - "node_modules/v8-compile-cache": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz", - "integrity": "sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==", - "dev": true - }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -34607,6 +34664,8 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dev": true, + "peer": true, "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -34978,6 +35037,8 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz", "integrity": "sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ==", + "dev": true, + "license": "MIT", "dependencies": { "bs58check": "<3.0.0" } @@ -34993,15 +35054,6 @@ "resolved": "https://registry.npmjs.org/wonka/-/wonka-4.0.15.tgz", "integrity": "sha512-U0IUQHKXXn6PFo9nqsHphVCE5m3IntqZNB9Jjn7EB1lrR7YTDY3YWgFvEvwniTzXSvOH/XMzAZaIfJF/LvHYXg==" }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -35059,18 +35111,6 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, - "node_modules/write": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", - "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", - "dev": true, - "dependencies": { - "mkdirp": "^0.5.1" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/write-file-atomic": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", @@ -35281,7 +35321,6 @@ "version": "20.2.9", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, "engines": { "node": ">=10" } diff --git a/package.json b/package.json index 56710c1386..75ec1e70f8 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "scripts": { "prepare": "husky install", "lint": "eslint . --fix", + "format": "prettier --write .", "start": "expo start --clear", "start:android": "expo start --clear --android", "start:ios": "expo start --clear --ios", @@ -17,6 +18,21 @@ "react-devtools:open": "react-devtools", "translation:missing": "ts-node shared/translations/reporter/index.ts" }, + "lint-staged": { + "*": "prettier --write --ignore-unknown" + }, + "prettier": "@waveshq/standard-prettier", + "eslintConfig": { + "parserOptions": { + "project": "./tsconfig.json" + }, + "extends": [ + "@stickyjs" + ], + "rules": { + "check-file/filename-naming-convention": "off" + } + }, "dependencies": { "@ethersproject/shims": "^5.7.0", "@expo-google-fonts/ibm-plex-sans": "^0.2.3", @@ -34,8 +50,6 @@ "@reduxjs/toolkit": "^1.9.7", "@shopify/flash-list": "1.6.3", "@waveshq/standard-defichain-jellyfishsdk": "^2.20.0", - "@waveshq/walletkit-core": "^1.3.10", - "@waveshq/walletkit-ui": "^1.3.10", "bignumber.js": "^9.1.2", "buffer": "^6.0.3", "classnames": "^2.3.2", @@ -94,7 +108,15 @@ "smart-buffer": "^4.2.0", "stream-browserify": "^3.0.0", "tailwind-rn": "^3.0.1", - "tailwindcss": "^2.2.19" + "tailwindcss": "^2.2.19", + "@stickyjs/jest": "^1.3.2", + "@stickyjs/eslint-config": "^1.3.2", + "@stickyjs/turbo": "^1.3.2", + "@waveshq/standard-web": "^4.0.1", + "@waveshq/standard-web-linter": "^4.0.1", + "immer": "^9.0.21", + "reselect": "^4.1.8", + "testcontainers": "^9.12.0" }, "devDependencies": { "@babel/core": "^7.23.2", @@ -120,16 +142,6 @@ "cypress": "^13.7.0", "cypress-image-diff-js": "^1.32.0", "eslint": "^8.52.0", - "eslint-config-airbnb": "^19.0.4", - "eslint-config-airbnb-typescript": "^17.1.0", - "eslint-config-node": "^4.1.0", - "eslint-config-prettier": "^9.0.0", - "eslint-plugin-cypress": "^2.15.1", - "eslint-plugin-jest": "27.4.3", - "eslint-plugin-prettier": "^5.0.1", - "eslint-plugin-react": "^7.33.2", - "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-react-native": "^4.1.0", "find-in-files": "^0.5.0", "husky": "^8.0.3", "jest": "^29.7.0", @@ -143,7 +155,14 @@ "ts-node": "^10.9.1", "typescript": "^5.3.0", "wait-on": "^7.2.0", - "webpack-merge": "^5.10.0" + "webpack-merge": "^5.10.0", + "@testing-library/jest-dom": "^5.17.0", + "@testing-library/react": "^14.0.0", + "@testing-library/react-hooks": "^7.0.2", + "@types/react": "17.0.0", + "jest-environment-jsdom": "^29.7.0", + "@waveshq/standard-defichain-jellyfishsdk": "^4.0.1", + "@waveshq/standard-prettier": "^4.0.1" }, "standard-version": { "skip": { @@ -163,5 +182,22 @@ "**.test.tsx", "**.snap" ] + }, + "jest": { + "preset": "@stickyjs/jest", + "testRegex": ".*.(unit|i9n|e2e|test).(ts|tsx)$", + "transform": { + "^.+\\.(ts|tsx)?$": "ts-jest", + "^.+\\.(js|jsx)$": "babel-jest" + }, + "moduleFileExtensions": [ + "ts", + "tsx", + "js", + "jsx" + ] + }, + "engines": { + "node": ">=18.0.0" } } diff --git a/shared/contexts/StatsProvider.tsx b/shared/contexts/StatsProvider.tsx index cea800837e..88dacf6284 100644 --- a/shared/contexts/StatsProvider.tsx +++ b/shared/contexts/StatsProvider.tsx @@ -2,11 +2,11 @@ import React, { useEffect, PropsWithChildren } from "react"; import { useSelector } from "react-redux"; import { isPlayground } from "@waveshq/walletkit-core"; import { RootState } from "@store"; -import { block } from "@waveshq/walletkit-ui/dist/store/block"; +import { block } from "@waveshq/walletkit-ui/store/block"; import { useNetworkContext } from "@waveshq/walletkit-ui"; import { useLogger } from "@shared-contexts/NativeLoggingProvider"; import { useAppDispatch } from "@hooks/useAppDispatch"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; export function StatsProvider( props: PropsWithChildren, diff --git a/shared/contexts/WalletDataProvider.tsx b/shared/contexts/WalletDataProvider.tsx index 8ddbbfc61c..219ded7860 100644 --- a/shared/contexts/WalletDataProvider.tsx +++ b/shared/contexts/WalletDataProvider.tsx @@ -9,13 +9,13 @@ import { fetchDexPrice, fetchPoolPairs, fetchTokens, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { fetchUserPreferences } from "@store/userPreferences"; import { useWalletContext } from "@shared-contexts/WalletContext"; import { fetchVaults } from "@store/loans"; import { useAppDispatch } from "@hooks/useAppDispatch"; import { useFeatureFlagContext } from "@contexts/FeatureFlagContext"; -import { useWhaleApiClient } from "@waveshq/walletkit-ui/dist/contexts"; +import { useWhaleApiClient } from "@waveshq/walletkit-ui/contexts"; export function WalletDataProvider( props: PropsWithChildren, diff --git a/shared/store/index.ts b/shared/store/index.ts index d12dce4261..2e3647ba56 100644 --- a/shared/store/index.ts +++ b/shared/store/index.ts @@ -8,7 +8,7 @@ import { wallet, announcementWebsiteSlice, statusWebsiteSlice, -} from "@waveshq/walletkit-ui/dist/store"; +} from "@waveshq/walletkit-ui/store"; import { authentication } from "./authentication"; import { loans } from "./loans"; import { auctions } from "./auctions"; diff --git a/tsconfig.json b/tsconfig.json index 4cbbc4faf1..5993be2712 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -33,7 +33,9 @@ "@store": ["../../shared/store"], "@store/*": ["../../shared/store/*"], "@translations": ["../../shared/translations"], - "@tailwind": ["tailwind"] + "@tailwind": ["tailwind"], + "@waveshq": ["../../walletkit"], + "@waveshq/*": ["../../walletkit/*"] } } } diff --git a/walletkit/walletkit-bot/api/DeFiChainCore.ts b/walletkit/walletkit-bot/api/DeFiChainCore.ts new file mode 100644 index 0000000000..3412097092 --- /dev/null +++ b/walletkit/walletkit-bot/api/DeFiChainCore.ts @@ -0,0 +1,124 @@ +import { fromAddress } from "@defichain/jellyfish-address"; +import { Script } from "@defichain/jellyfish-transaction"; +import { + JellyfishWallet, + WalletHdNode, + WalletHdNodeProvider, +} from "@defichain/jellyfish-wallet"; +import { + MnemonicHdNodeProvider, + MnemonicProviderData, + validateMnemonicSentence, +} from "@defichain/jellyfish-wallet-mnemonic"; +import { WhaleApiClient } from "@defichain/whale-api-client"; +import { + WhaleWalletAccount, + WhaleWalletAccountProvider, +} from "@defichain/whale-api-wallet"; +import { + EnvironmentNetwork, + getBip32Option, + getJellyfishNetwork, +} from "@waveshq/walletkit-core"; +import { BigNumber } from "bignumber.js"; + +enum WalletType { + MNEMONIC_UNPROTECTED = "MNEMONIC_UNPROTECTED", + MNEMONIC_ENCRYPTED = "MNEMONIC_ENCRYPTED", +} + +interface WalletPersistenceDataI { + type: WalletType; + /* To migrate between app version upgrade */ + version: "v1"; + /* Raw Data encoded in WalletType specified format */ + raw: T; +} + +export function toData( + mnemonic: string[], + envNetwork: EnvironmentNetwork, +): WalletPersistenceDataI { + const options = getBip32Option(envNetwork); + const data = MnemonicHdNodeProvider.wordsToData(mnemonic, options); + + return { + version: "v1", + type: WalletType.MNEMONIC_UNPROTECTED, + raw: data, + }; +} + +export function initProvider( + data: WalletPersistenceDataI, + envNetwork: EnvironmentNetwork, +): MnemonicHdNodeProvider { + if (data.type !== WalletType.MNEMONIC_UNPROTECTED || data.version !== "v1") { + throw new Error("Unexpected WalletPersistenceDataI"); + } + + const options = getBip32Option(envNetwork); + return MnemonicHdNodeProvider.fromData(data.raw, options); +} + +export function initJellyfishWallet( + provider: WalletHdNodeProvider, + urlNetwork: string, + envNetwork: EnvironmentNetwork, +): JellyfishWallet { + const client = getWhaleClient(urlNetwork, envNetwork); + const accountProvider = new WhaleWalletAccountProvider( + client, + getJellyfishNetwork(envNetwork), + ); + return new JellyfishWallet(provider, accountProvider); +} + +export function createWallet( + urlNetwork: string, + envNetwork: EnvironmentNetwork, + mnemonic: string, + index: number = 0, +): WhaleWalletAccount { + if (!validateMnemonicSentence(mnemonic)) { + throw new Error("Invalid DeFiChain mnemonic!"); + } + const data = toData(mnemonic.split(" "), envNetwork); + const provider = initProvider(data, envNetwork); + return initJellyfishWallet(provider, urlNetwork, envNetwork).get(index); +} + +export function getWhaleClient( + urlNetwork: string, + envNetwork: EnvironmentNetwork, +): WhaleApiClient { + return new WhaleApiClient({ + url: urlNetwork, + version: "v0", + network: getJellyfishNetwork(envNetwork).name, + }); +} + +export function getAddressScript( + address: string, + envNetwork: EnvironmentNetwork, +): Script { + const decodedAddress = fromAddress( + address, + getJellyfishNetwork(envNetwork).name, + ); + if (decodedAddress === undefined) { + throw new Error(`Unable to decode Address - ${address}`); + } + return decodedAddress.script; +} + +/** + * Get current wallet UTXO balance + */ +export async function getUTXOBalance( + address: string, + client: WhaleApiClient, +): Promise { + return new BigNumber(await client.address.getBalance(address)); +} diff --git a/walletkit/walletkit-bot/api/RefundBot.ts b/walletkit/walletkit-bot/api/RefundBot.ts new file mode 100644 index 0000000000..f3d136d8f7 --- /dev/null +++ b/walletkit/walletkit-bot/api/RefundBot.ts @@ -0,0 +1,127 @@ +/* eslint-disable no-console */ +import { + CTransactionSegWit, + TransactionSegWit, +} from "@defichain/jellyfish-transaction"; +import { WhaleWalletAccount } from "@defichain/whale-api-wallet"; +import { + EnvironmentNetwork, + getJellyfishNetwork, +} from "@waveshq/walletkit-core"; +import { BigNumber } from "bignumber.js"; + +import { + createWallet, + getAddressScript, + getWhaleClient, +} from "./DeFiChainCore"; + +export interface HandlerProps { + index: number; // index of wallet's derived from parent private keys + refundAddress: string; + claimAmount: string; // the amount that the user wants to be refunded + tokenSymbol: string; + urlNetwork: string; + envNetwork: EnvironmentNetwork; + mnemonic: string; +} + +export async function handler(props: HandlerProps): Promise { + try { + const { + index, + refundAddress, + claimAmount, + tokenSymbol, + urlNetwork, + mnemonic, + envNetwork, + } = props; + + const client = getWhaleClient(urlNetwork, envNetwork); + const network = getJellyfishNetwork(envNetwork); + const account = new WhaleWalletAccount( + client, + createWallet(urlNetwork, envNetwork, mnemonic, index), + network, + ); + + // Checks for invalid arguments from the database + if (Number(index) < 0) { + throw new Error(`${index} not a valid index`); + } + + if ( + new BigNumber(claimAmount).isLessThanOrEqualTo(0) || + new BigNumber(claimAmount).isNaN() + ) { + throw new Error(`Invalid claim amount: ${new BigNumber(claimAmount)}`); + } + + if (tokenSymbol === undefined || tokenSymbol === "") { + throw new Error(`Token symbol is undefined`); + } + + // Gives back the id of the tokenSymbol + // eslint-disable-next-line no-restricted-properties + const tokenId = (await account.client.tokens.list()).find( + (token) => token.symbol === tokenSymbol && token.isDAT, // to ensure that its DeFiChain's official token + )?.id; + + if (tokenId === undefined) { + throw new Error("tokenId is undefined"); + } + + const from = await account.getScript(); + const to = getAddressScript(refundAddress, envNetwork); + // Allows support for UTXO transactions + const builder = await account.withTransactionBuilder(); + + const isDFI = tokenSymbol === "DFI"; // Assumed DFI UTXO + + let txn: TransactionSegWit; + + if (isDFI) { + // Sends DFI UTXO, not Tokens back to refundAddress + const fees = 0.001; + const amountToClaim = new BigNumber(claimAmount); + + if (amountToClaim.isLessThanOrEqualTo(fees)) { + throw new Error(`Not enough amount to cover txn fees`); + } else { + txn = await builder.utxo.send(amountToClaim.minus(fees), to, from); + } + } else { + // Only sends Tokens + txn = await builder.account.accountToAccount( + { + from, + to: [ + { + script: to, + balances: [ + { + token: Number(tokenId), + amount: new BigNumber(claimAmount), + }, + ], + }, + ], + }, + from, + ); + } + + // eslint-disable-next-line @typescript-eslint/no-shadow, no-inner-declarations + async function broadcast(txn: TransactionSegWit): Promise { + const hex: string = new CTransactionSegWit(txn).toHex(); + const txId: string = await client.rawtx.send({ hex }); + + return console.log(`Send TxId: ${txId}`); // added return for unit testing + } + + await broadcast(txn); + } catch (error) { + console.log((error as Error).message); + } +} diff --git a/walletkit/walletkit-bot/api/RefundBot.unit.ts b/walletkit/walletkit-bot/api/RefundBot.unit.ts new file mode 100644 index 0000000000..e5adcc8d4c --- /dev/null +++ b/walletkit/walletkit-bot/api/RefundBot.unit.ts @@ -0,0 +1,117 @@ +import { EnvironmentNetwork } from "@waveshq/walletkit-core/src"; + +import { handler, HandlerProps } from "./RefundBot"; + +const DFC_PLAYGROUND_MNEMONIC = + "decorate unable decide notice wear unusual detail frost tissue debate opera luggage change chest broom attract divert fine quantum citizen veteran carbon draft matter"; + +const DFC_INVALID_PLAYGROUND_MNEMONIC = + "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon"; + +const REFUND_PLAYGROUND_ADDRESS = + "bcrt1qlmvmz3wvfm945txx3hsyresqep4ywylpwvqa0w"; + +const INVALID_REFUND_PLAYGROUND_ADDRESS = "invalidaddress"; + +test.skip("should return transaction id when succesfully refunded ETH tokens (with manual topup of UTXO)", async () => { + await spiedConsoleWithReturnResponse( + { + index: 0, + refundAddress: REFUND_PLAYGROUND_ADDRESS, + claimAmount: "0.1994", + tokenSymbol: "ETH", + urlNetwork: "https://playground.jellyfishsdk.com", + envNetwork: EnvironmentNetwork.RemotePlayground, + mnemonic: DFC_PLAYGROUND_MNEMONIC, + }, + expect.stringMatching(/Send TxId:/), + ); +}); + +// Received: [Error: 400 - BadRequest (/v0/regtest/rawtx/send): txn-mempool-conflict (code 18)] +// Can't send another transaction immediately +test.skip("should return transaction id when succesfully refunded DFI UTXO (with manual topup of UTXO)", async () => { + await spiedConsoleWithReturnResponse( + { + index: 0, + refundAddress: REFUND_PLAYGROUND_ADDRESS, + claimAmount: "0.5", + tokenSymbol: "DFI", + urlNetwork: "https://playground.jellyfishsdk.com", + envNetwork: EnvironmentNetwork.RemotePlayground, + mnemonic: DFC_PLAYGROUND_MNEMONIC, + }, + expect.stringMatching(/Send TxId:/), + ); +}); + +test("should return invalid DeFiChain private keys", async () => { + await spiedConsoleWithReturnErrorResponse( + { + index: 0, + refundAddress: REFUND_PLAYGROUND_ADDRESS, + claimAmount: "0.1994", + tokenSymbol: "ETH", + urlNetwork: "https://playground.jellyfishsdk.com", + envNetwork: EnvironmentNetwork.RemotePlayground, + mnemonic: DFC_INVALID_PLAYGROUND_MNEMONIC, + }, + "Invalid DeFiChain private keys!", + ); +}); + +test("should return unable to decode address given the wrong refund address' index", async () => { + await spiedConsoleWithReturnErrorResponse( + { + index: -10, + refundAddress: INVALID_REFUND_PLAYGROUND_ADDRESS, + claimAmount: "0.1994", + tokenSymbol: "ETH", + urlNetwork: "https://playground.jellyfishsdk.com", + envNetwork: EnvironmentNetwork.RemotePlayground, + mnemonic: DFC_PLAYGROUND_MNEMONIC, + }, + "Invalid DeFiChain private keys!", + ); +}); + +test("should return unable to decode address given the wrong refund address", async () => { + await spiedConsoleWithReturnErrorResponse( + { + index: 0, + refundAddress: INVALID_REFUND_PLAYGROUND_ADDRESS, + claimAmount: "0.1994", + tokenSymbol: "ETH", + urlNetwork: "https://playground.jellyfishsdk.com", + envNetwork: EnvironmentNetwork.RemotePlayground, + mnemonic: DFC_PLAYGROUND_MNEMONIC, + }, + `Unable to decode Address - ${INVALID_REFUND_PLAYGROUND_ADDRESS}`, + ); +}); + +async function spiedConsoleWithReturnResponse( + mockedObject: HandlerProps, + errorMessage: string, +): Promise { + const consoleSpy = jest.spyOn(console, "log"); + try { + await handler(mockedObject); + expect(consoleSpy).toHaveBeenCalledWith(errorMessage); + } finally { + consoleSpy.mockRestore(); + } +} +async function spiedConsoleWithReturnErrorResponse( + mockedObject: HandlerProps, + errorMessage: string, +): Promise { + const consoleSpy = jest.spyOn(console, "log").mockImplementation(); + try { + await handler(mockedObject); + } catch (err) { + expect(err).toBeDefined(); + expect(consoleSpy).toHaveBeenCalledWith(errorMessage); + } + consoleSpy.mockRestore(); +} diff --git a/walletkit/walletkit-bot/api/StateRelayerBot.ts b/walletkit/walletkit-bot/api/StateRelayerBot.ts new file mode 100644 index 0000000000..7f1681c4e7 --- /dev/null +++ b/walletkit/walletkit-bot/api/StateRelayerBot.ts @@ -0,0 +1,95 @@ +/* eslint-disable no-console */ +import { EnvironmentNetwork } from "@waveshq/walletkit-core"; +import { BigNumber } from "bignumber.js"; + +import { getWhaleClient } from "./DeFiChainCore"; + +type PairData = { + [pairSymbol: string]: { + primaryTokenPrice: string; + volume24H: string; + totalLiquidity: string; + apr: string; + }; +}; + +type DataStore = { + // /dex + totalValueLockInPoolPair: string; + total24HVolume: string; + pair: PairData; +}; + +type StateRelayerHandlerProps = { + urlNetwork: string; + envNetwork: EnvironmentNetwork; +}; + +const DENOMINATION = "USDT"; + +export async function handler( + props: StateRelayerHandlerProps, +): Promise { + const { urlNetwork, envNetwork } = props; + const dataStore = {} as DataStore; + try { + // TODO: Check if Function should run (blockHeight > 30 from previous) + // Get Data from OCEAN API + const client = getWhaleClient(urlNetwork, envNetwork); + const statsData = await client.stats.get(); + const rawPoolpairData = await client.poolpairs.list(200); + const dexPriceData = await client.poolpairs.listDexPrices(DENOMINATION); + + // sanitise response data + const poolpairData = rawPoolpairData.filter( + (pair: any) => !pair.displaySymbol.includes("/"), + ); + + /* ------------ Data from /dex ----------- */ + // totalValueLockInPoolPair + dataStore.totalValueLockInPoolPair = statsData.tvl.dex.toString(); + + // total24HVolume + const total24HVolume = poolpairData.reduce( + (acc, currPair) => acc + (currPair.volume?.h24 ?? 0), + 0, + ); + dataStore.total24HVolume = total24HVolume.toString(); + + // pair + const pair = poolpairData.reduce((acc, currPair) => { + let tokenPrice = new BigNumber(0); + const priceRatio = currPair.priceRatio.ba; + const { symbol } = currPair.tokenB; + if (symbol === DENOMINATION || new BigNumber(priceRatio).isZero()) { + tokenPrice = new BigNumber(0); + } else { + const dexPricePerToken = new BigNumber( + dexPriceData.dexPrices[symbol].denominationPrice ?? 0, + ); + tokenPrice = dexPricePerToken.multipliedBy(currPair.priceRatio.ba); + } + return { + ...acc, + [currPair.displaySymbol]: { + primaryTokenPrice: tokenPrice.toString(), + volume24H: currPair?.volume?.h24.toString() ?? "0", + totalLiquidity: currPair.totalLiquidity.usd ?? "0", + apr: currPair?.apr?.total.toString(), + }, + } as PairData; + }, {} as PairData); + dataStore.pair = pair; + // TODO: Get Data from /dex/[pool-pair] + // TODO: Get Data from /vaults + // TODO: Get Data from /masternodes + // TODO: Get Data from all burns in ecosystem + // Interfacing with SC + // TODO: Connect with SC + // TODO: Call SC Function to update Collated Data + return dataStore; + } catch (e) { + console.error((e as Error).message); + return undefined; + } +} diff --git a/walletkit/walletkit-bot/api/StateRelayerBot.unit.ts b/walletkit/walletkit-bot/api/StateRelayerBot.unit.ts new file mode 100644 index 0000000000..8f3476c77c --- /dev/null +++ b/walletkit/walletkit-bot/api/StateRelayerBot.unit.ts @@ -0,0 +1,52 @@ +import { EnvironmentNetwork } from "@waveshq/walletkit-core"; + +import { + expectedPairData, + mockedDexPricesData, + mockedPoolPairData, + mockedStatsData, +} from "../utils/oceanMockedData"; +import { handler } from "./StateRelayerBot"; + +jest.mock("@defichain/whale-api-client", () => ({ + WhaleApiClient: jest.fn().mockImplementation(() => ({ + stats: { + get: () => mockedStatsData, + }, + poolpairs: { + list: () => mockedPoolPairData, + listDexPrices: () => mockedDexPricesData, + }, + })), +})); + +describe("State Relayer Bot Tests", () => { + test("should check block height difference is more than 30", () => {}); + test("should check that data is parsed correctly", async () => { + const response = await runHandler(); + expect(response).toBeDefined(); + + // should check data from /dex is parsed correctly + expect(response).toHaveProperty( + "totalValueLockInPoolPair", + "272281685.3262795", + ); + expect(response).toHaveProperty("total24HVolume", "60010"); + expect(response).toHaveProperty("pair", expectedPairData); + + // should check data from /dex/[pool-pair] is parsed correctly + + // should check data from /vaults is parsed correctly + + // should check data from /masternodes is parsed correctly + + // should check data from all burns is parsed correctly + }); +}); + +async function runHandler() { + return handler({ + envNetwork: EnvironmentNetwork.LocalPlayground, + urlNetwork: "", + }); +} diff --git a/walletkit/walletkit-bot/api/index.ts b/walletkit/walletkit-bot/api/index.ts new file mode 100644 index 0000000000..5513979c9a --- /dev/null +++ b/walletkit/walletkit-bot/api/index.ts @@ -0,0 +1,3 @@ +export * from "./DeFiChainCore"; +export * from "./RefundBot"; +export * as SRHandler from "./StateRelayerBot"; diff --git a/walletkit/walletkit-bot/index.ts b/walletkit/walletkit-bot/index.ts new file mode 100644 index 0000000000..d158c57640 --- /dev/null +++ b/walletkit/walletkit-bot/index.ts @@ -0,0 +1 @@ +export * from "./api"; diff --git a/walletkit/walletkit-bot/utils/oceanMockedData.ts b/walletkit/walletkit-bot/utils/oceanMockedData.ts new file mode 100644 index 0000000000..e5307a34ba --- /dev/null +++ b/walletkit/walletkit-bot/utils/oceanMockedData.ts @@ -0,0 +1,426 @@ +export const mockedStatsData = { + count: { + blocks: 2860706, + prices: 145, + tokens: 221, + masternodes: 15044, + }, + burned: { + address: 156047252.270101, + fee: 315015.5, + auction: 1512527.37726055, + payback: 61705058.1749106, + emission: 98783549.5707572, + total: 317634155.7199576, + }, + tvl: { + dex: 272281685.3262795, + masternodes: 152862005.47177258, + loan: 181660513.6278827, + total: 606804204.4259348, + }, + price: { + usd: 0.4935809023951326, + usdt: 0.4935809023951326, + }, + masternodes: { + locked: [ + { + weeks: 0, + count: 10636, + tvl: 109372690.57990181, + }, + { + weeks: 520, + count: 3491, + tvl: 34469627.40944635, + }, + { + weeks: 260, + count: 917, + tvl: 9054324.931097768, + }, + ], + }, + loan: { + count: { + collateralTokens: 7, + loanTokens: 56, + openAuctions: 1, + openVaults: 11424, + schemes: 6, + }, + value: { + collateral: 181011671.8179531, + loan: 84857375.19502015, + }, + }, + emission: { + masternode: 49.50800321, + dex: 37.80314077, + community: 7.2932582, + anchor: 0.02970777, + burned: 53.904753576004445, + total: 148.53886352600443, + }, + net: { + version: 3020800, + subversion: "/DeFiChain:3.2.8/", + protocolversion: 70036, + }, + blockchain: { + difficulty: 40436424028.63132, + }, +}; + +export const mockedPoolPairData = [ + { + id: "4", + symbol: "ETH-DFI", + displaySymbol: "dETH-DFI", + name: "Ether-Default Defi token", + status: true, + tokenA: { + symbol: "ETH", + displaySymbol: "dETH", + id: "1", + name: "Ether", + reserve: "6084.54409371", + blockCommission: "0", + }, + tokenB: { + symbol: "DFI", + displaySymbol: "DFI", + id: "0", + name: "Default Defi token", + reserve: "24609913.43738302", + blockCommission: "0", + }, + priceRatio: { + ab: "0.00024723", + ba: "4044.66021748", + }, + commission: "0.002", + totalLiquidity: { + token: "386541.57956427", + usd: "25636863.24062524435653579327168029", + }, + tradeEnabled: true, + ownerAddress: "8UAhRuUFCyFUHEPD7qvtj8Zy2HxF5HH5nb", + rewardPct: "0.13086", + rewardLoanPct: "0", + creation: { + tx: "9827894c083b77938d13884f0404539daa054a818e0c5019afa1eeff0437a51b", + height: 466822, + }, + apr: { + reward: 0.10565257112251523, + commission: 0.006194303259455489, + total: 0.11184687438197073, + }, + volume: { + h24: 12000, + d30: 9384652.670150768, + }, + }, + { + id: "5", + symbol: "BTC-DFI", + displaySymbol: "dBTC-DFI", + name: "Bitcoin-Default Defi token", + status: true, + tokenA: { + symbol: "BTC", + displaySymbol: "dBTC", + id: "2", + name: "Bitcoin", + reserve: "1906.53033325", + blockCommission: "0", + fee: { + pct: "0.001", + inPct: "0.001", + outPct: "0.001", + }, + }, + tokenB: { + symbol: "DFI", + displaySymbol: "DFI", + id: "0", + name: "Default Defi token", + reserve: "110882651.06540145", + blockCommission: "0", + }, + priceRatio: { + ab: "0.00001719", + ba: "58159.39517541", + }, + commission: "0.002", + totalLiquidity: { + token: "459594.97245415", + usd: "115509685.491358337662696092943679775", + }, + tradeEnabled: true, + ownerAddress: "8UAhRuUFCyFUHEPD7qvtj8Zy2HxF5HH5nb", + rewardPct: "0.67383", + rewardLoanPct: "0", + creation: { + tx: "f3c99e199d0157b2b6254cf3a51bb1171569ad5c4beb797e957d245aec194d38", + height: 466826, + }, + apr: { + reward: 0.12074522976211577, + commission: 0.004496521422034606, + total: 0.12524175118415037, + }, + volume: { + h24: 12001, + d30: 20157262.644748364, + }, + }, + { + id: "6", + symbol: "USDT-DFI", + displaySymbol: "dUSDT-DFI", + name: "Tether USD-Default Defi token", + status: true, + tokenA: { + symbol: "USDT", + displaySymbol: "dUSDT", + id: "3", + name: "Tether USD", + reserve: "2840795.72929717", + blockCommission: "0", + }, + tokenB: { + symbol: "DFI", + displaySymbol: "DFI", + id: "0", + name: "Default Defi token", + reserve: "5453921.39411839", + blockCommission: "0", + }, + priceRatio: { + ab: "0.52087214", + ba: "1.91985693", + }, + commission: "0.002", + totalLiquidity: { + token: "3908049.73263869", + usd: "5681591.45859434", + }, + tradeEnabled: true, + ownerAddress: "8UAhRuUFCyFUHEPD7qvtj8Zy2HxF5HH5nb", + rewardPct: "0.02909", + rewardLoanPct: "0", + creation: { + tx: "37939243c7dbacb2675cfc4e0632e9bf829dcc5cece2928f235fba4b03c09a6a", + height: 466826, + }, + apr: { + reward: 0.1059770338938296, + commission: 0.0159031293880106, + total: 0.1218801632818402, + }, + volume: { + h24: 12002, + d30: 11394557.050918248, + }, + }, + { + id: "8", + symbol: "DOGE-DFI", + displaySymbol: "dDOGE-DFI", + name: "Dogecoin-Default Defi token", + status: true, + tokenA: { + symbol: "DOGE", + displaySymbol: "dDOGE", + id: "7", + name: "Dogecoin", + reserve: "2238975.88572023", + blockCommission: "0", + }, + tokenB: { + symbol: "DFI", + displaySymbol: "DFI", + id: "0", + name: "Default Defi token", + reserve: "400276.86840847", + blockCommission: "0", + }, + priceRatio: { + ab: "5.593568", + ba: "0.17877676", + }, + commission: "0.002", + totalLiquidity: { + token: "931088.8215018", + usd: "416980.066178766746375664018708065", + }, + tradeEnabled: true, + ownerAddress: "8UAhRuUFCyFUHEPD7qvtj8Zy2HxF5HH5nb", + rewardPct: "0", + rewardLoanPct: "0", + creation: { + tx: "9e0c956f9c626c07ba3dd742748ff9872b5688a976d66d35aa09418f18620b64", + height: 607452, + }, + apr: { + reward: 0, + commission: 0.013596317989663933, + total: 0.013596317989663933, + }, + volume: { + h24: 12003, + d30: 711633.5942259821, + }, + }, + { + id: "10", + symbol: "LTC-DFI", + displaySymbol: "dLTC-DFI", + name: "Litecoin-Default Defi token", + status: true, + tokenA: { + symbol: "LTC", + displaySymbol: "dLTC", + id: "9", + name: "Litecoin", + reserve: "11904.19924637", + blockCommission: "0", + }, + tokenB: { + symbol: "DFI", + displaySymbol: "DFI", + id: "0", + name: "Default Defi token", + reserve: "2317337.42661253", + blockCommission: "0", + }, + priceRatio: { + ab: "0.00513701", + ba: "194.66554437", + }, + commission: "0.002", + totalLiquidity: { + token: "162557.66984317", + usd: "2414037.856720123393447225830671435", + }, + tradeEnabled: true, + ownerAddress: "8UAhRuUFCyFUHEPD7qvtj8Zy2HxF5HH5nb", + rewardPct: "0", + rewardLoanPct: "0", + creation: { + tx: "75a25a52c54d12f84d4a553be354fa2c5651689d8f9f4860aad8b68c804af3f1", + height: 614026, + }, + apr: { + reward: 0, + commission: 0.00819656242847228, + total: 0.00819656242847228, + }, + volume: { + h24: 12004, + d30: 2089677.4183758958, + }, + }, +]; + +export const mockedDexPricesData = { + denomination: { + id: "3", + name: "Tether USD", + symbol: "USDT", + displaySymbol: "dUSDT", + }, + dexPrices: { + DFI: { + token: { + id: "0", + name: "Default Defi token", + symbol: "DFI", + displaySymbol: "DFI", + }, + denominationPrice: "0.51229009", + }, + ETH: { + token: { + id: "1", + name: "Ether", + symbol: "ETH", + displaySymbol: "dETH", + }, + denominationPrice: "2126.78379968", + }, + BTC: { + token: { + id: "2", + name: "Bitcoin", + symbol: "BTC", + displaySymbol: "dBTC", + }, + denominationPrice: "30022.91758081", + }, + DOGE: { + token: { + id: "7", + name: "Dogecoin", + symbol: "DOGE", + displaySymbol: "dDOGE", + }, + denominationPrice: "0.09458052", + }, + LTC: { + token: { + id: "9", + name: "Litecoin", + symbol: "LTC", + displaySymbol: "dLTC", + }, + denominationPrice: "103.65046666", + }, + USDC: { + token: { + id: "13", + name: "USD Coin", + symbol: "USDC", + displaySymbol: "dUSDC", + }, + denominationPrice: "1.01551234", + }, + }, +}; + +// generated fixtures from mocked data above +export const expectedPairData = { + "dETH-DFI": { + primaryTokenPrice: "2072.0393468322487732", + volume24H: "12000", + totalLiquidity: "25636863.24062524435653579327168029", + apr: "0.11184687438197073", + }, + "dBTC-DFI": { + primaryTokenPrice: "29794.4817887563546869", + volume24H: "12001", + totalLiquidity: "115509685.491358337662696092943679775", + apr: "0.12524175118415037", + }, + "dUSDT-DFI": { + primaryTokenPrice: "0.9835236794568237", + volume24H: "12002", + totalLiquidity: "5681591.45859434", + apr: "0.1218801632818402", + }, + "dDOGE-DFI": { + primaryTokenPrice: "0.0915855624703084", + volume24H: "12003", + totalLiquidity: "416980.066178766746375664018708065", + apr: "0.013596317989663933", + }, + "dLTC-DFI": { + primaryTokenPrice: "99.7252292452062933", + volume24H: "12004", + totalLiquidity: "2414037.856720123393447225830671435", + apr: "0.00819656242847228", + }, +}; diff --git a/walletkit/walletkit-core/api/__snapshots__/network.unit.ts.snap b/walletkit/walletkit-core/api/__snapshots__/network.unit.ts.snap new file mode 100644 index 0000000000..495a689b39 --- /dev/null +++ b/walletkit/walletkit-core/api/__snapshots__/network.unit.ts.snap @@ -0,0 +1,51 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`network should resolve bip32 option for Changi 1`] = ` +{ + "bip32": { + "private": 70615956, + "public": 70617039, + }, + "wif": 239, +} +`; + +exports[`network should resolve bip32 option for LocalPlayground 1`] = ` +{ + "bip32": { + "private": 70615956, + "public": 70617039, + }, + "wif": 239, +} +`; + +exports[`network should resolve bip32 option for MainNet 1`] = ` +{ + "bip32": { + "private": 76066276, + "public": 76067358, + }, + "wif": 128, +} +`; + +exports[`network should resolve bip32 option for RemotePlayground 1`] = ` +{ + "bip32": { + "private": 70615956, + "public": 70617039, + }, + "wif": 239, +} +`; + +exports[`network should resolve bip32 option for TestNet 1`] = ` +{ + "bip32": { + "private": 70615956, + "public": 70617039, + }, + "wif": 239, +} +`; diff --git a/walletkit/walletkit-core/api/address.ts b/walletkit/walletkit-core/api/address.ts new file mode 100644 index 0000000000..6634f0e853 --- /dev/null +++ b/walletkit/walletkit-core/api/address.ts @@ -0,0 +1,106 @@ +import { Eth, fromAddress, fromScript } from "@defichain/jellyfish-address"; +import { NetworkName } from "@defichain/jellyfish-network"; +import { Script } from "@defichain/jellyfish-transaction"; +import { ethers } from "ethers"; + +/** + * Known Address Types from jellyfish-address + */ +export enum AddressType { + /** + * Pay to Witness Public Key Hash + * Native SEGWIT with Bech32 + */ + P2WPKH = "P2WPKH", + /** + * Pay to Witness Script Hash + * Native SEGWIT with Bech32 + */ + P2WSH = "P2WSH", + /** + * Pay to Script Hash + */ + P2SH = "P2SH", + /** + * Pay to Public Key Hash + * Also known as legacy + */ + P2PKH = "P2PKH", + /** + * Ethereum address + */ + ETH = "ETH", +} + +export interface EthDecodedAddress { + type: AddressType; + address: string; + script: Script; + network: NetworkName; +} + +export function getDecodedAddress( + script: Script, + network: NetworkName, +): EthDecodedAddress | undefined { + try { + // check if is dfc address first + const decodedAddress = fromScript(script, network); + if (decodedAddress !== undefined) { + return decodedAddress; + } + + // check if eth address + /* SAMPLE of script object + "script": { + "stack": [ + { + "type": "OP_0", + "code": 0 + }, + { + "type": "OP_PUSHDATA", + "hex": "f23d101c17445dba29b99f5c82186990b2b2c6bf" + } + ] + }, + */ + + // extract script OPCodes and Hex + const decodedEthAddress = Eth.fromScript(script); + if (decodedEthAddress !== undefined) { + return { + type: AddressType.ETH, + address: `0x${decodedEthAddress}`, + script, + network, + }; + } + + return undefined; + } catch (e) { + return undefined; + } +} + +export function getAddressType( + address: string, + network: NetworkName, +): AddressType | undefined { + try { + // check if is dfc address first + const decodedAddress = fromAddress(address, network); + if (decodedAddress !== undefined) { + return decodedAddress.type; + } + + // check if the address is evm + const isEVMAddress = ethers.utils.isAddress(address); + if (isEVMAddress) { + return AddressType.ETH; + } + return undefined; + } catch (e) { + return undefined; + } +} diff --git a/walletkit/walletkit-core/api/address.unit.ts b/walletkit/walletkit-core/api/address.unit.ts new file mode 100644 index 0000000000..da7963bafa --- /dev/null +++ b/walletkit/walletkit-core/api/address.unit.ts @@ -0,0 +1,113 @@ +import { OP_CODES, Script } from "@defichain/jellyfish-transaction"; + +import { + AddressType, + EthDecodedAddress, + getAddressType, + getDecodedAddress, +} from "./address"; + +/* detailed `fromScript()` test cases are done in @defichain/jellyfish-address */ +describe("Address Decoder", () => { + it("should be able to decode valid DFC script", () => { + const script: Script = { + stack: [ + OP_CODES.OP_0, + OP_CODES.OP_PUSHDATA_HEX_LE( + "9e1be07558ea5cc8e02ed1d80c0911048afad949affa36d5c3951e3159dbea19", + ), + ], + }; + + const expected: EthDecodedAddress = { + type: AddressType.P2WSH, + address: "tf1qncd7qa2cafwv3cpw68vqczg3qj904k2f4lard4wrj50rzkwmagvsemeex5", + script, + network: "testnet", + }; + expect(getDecodedAddress(script, "testnet")).toStrictEqual(expected); + }); + + it("should be able to decode valid ETH script", () => { + const script: Script = { + stack: [ + OP_CODES.OP_16, + OP_CODES.OP_PUSHDATA_HEX_BE("98bd4c07f8eddf293f81e511921106d0c7f2839d"), + ], + }; + + const expected: EthDecodedAddress = { + type: AddressType.ETH, + address: "0x98bd4c07f8eddf293f81e511921106d0c7f2839d", + script, + network: "testnet", + }; + + expect(getDecodedAddress(script, "testnet")).toStrictEqual(expected); + }); + + it("should return undefined for invalid DFC script, if [0] != OP_0", () => { + const script: Script = { + stack: [ + OP_CODES.OP_1, + OP_CODES.OP_PUSHDATA_HEX_LE( + "9e1be07558ea5cc8e02ed1d80c0911048afad949affa36d5c3951e3159dbea19", + ), + ], + }; + + expect(getDecodedAddress(script, "testnet")).toBeUndefined(); + }); + + it("should return undefined for ETH script, if [1] != OP_PUSHDATA", () => { + const script: Script = { + stack: [OP_CODES.OP_16, OP_CODES.OP_RETURN], + }; + + expect(getDecodedAddress(script, "testnet")).toBeUndefined(); + }); + + it("should return undefined for invalid ETH hex", () => { + const script: Script = { + stack: [ + OP_CODES.OP_16, + OP_CODES.OP_PUSHDATA_HEX_LE( + "9e1be07558ea5cc8e02ed1d80c0911048afad949affa36d5c3951e3159dbea19", + ), + ], + }; + + expect(getDecodedAddress(script, "testnet")).toBeUndefined(); + }); +}); + +describe("Get Address Type", () => { + const addresses = [ + { + address: "tf1qzvvn8rp2q93w5rf9afpjjm2w2wtuu2fnvl6j3p", + type: AddressType.P2WPKH, + }, + { + address: "tf1qncd7qa2cafwv3cpw68vqczg3qj904k2f4lard4wrj50rzkwmagvsemeex5", + type: AddressType.P2WSH, + }, + { address: "77nPza1LqwQzS9jMCnxVV3xKYWnLLZePwo", type: AddressType.P2PKH }, + { address: "tkwD8teFiwr9fGwwX2KfgrgYRbwEiWmMJw", type: AddressType.P2SH }, + { + address: "0xe36f18af5bFfDcB442E84970408F68570aB88F52", + type: AddressType.ETH, + }, + ]; + + addresses.forEach(({ address, type }) => { + it(`should be able to get valid ${type} address type`, () => { + expect(getAddressType(address, "testnet")).toStrictEqual(type); + }); + }); + + it(`should be able to get valid undefined with wrong address`, () => { + expect( + getAddressType("bcrt1q6cxskutl6jf0jjeqxc3ymfuqakhw4r247tht58", "testnet"), + ).toStrictEqual(undefined); + }); +}); diff --git a/walletkit/walletkit-core/api/addressValidator.ts b/walletkit/walletkit-core/api/addressValidator.ts new file mode 100644 index 0000000000..e56b75df28 --- /dev/null +++ b/walletkit/walletkit-core/api/addressValidator.ts @@ -0,0 +1,10 @@ +import { fromAddress } from "@defichain/jellyfish-address"; +import { NetworkName } from "@defichain/jellyfish-network"; + +export const validateAddress = ( + address: string, + network: NetworkName, +): boolean => { + const decodedAddress = fromAddress(address, network); + return decodedAddress !== undefined; +}; diff --git a/walletkit/walletkit-core/api/addressValidator.unit.ts b/walletkit/walletkit-core/api/addressValidator.unit.ts new file mode 100644 index 0000000000..7c5792ddb8 --- /dev/null +++ b/walletkit/walletkit-core/api/addressValidator.unit.ts @@ -0,0 +1,39 @@ +import { validateAddress } from "./addressValidator"; + +const WALLET_ADDRESS = { + mainnet: "df1qldycdkvqaacwsf4gmgl29mt686mh95kattran0", + testnet: "tf1qm5hf2lhrsyfzeu0mnnzl3zllznfveua5rprhr4", + regtest: "bcrt1qh2yq58tzsh4gled7wv98mm7lndj9u5v6zyr2ge", +}; + +describe("Address validator", () => { + it("should be valid DFC address for Mainnet network", () => { + const isValidAddress = validateAddress(WALLET_ADDRESS.mainnet, "mainnet"); + expect(isValidAddress).toBeTruthy(); + }); + + it("should be valid DFC address for Testnet network", () => { + const isValidAddress = validateAddress(WALLET_ADDRESS.testnet, "testnet"); + expect(isValidAddress).toBeTruthy(); + }); + + it("should be valid DFC address for Regtest network", () => { + const isValidAddress = validateAddress(WALLET_ADDRESS.regtest, "regtest"); + expect(isValidAddress).toBeTruthy(); + }); + + it("should be invalid when a Mainnet address is used on Testnet network", () => { + const isValidAddress = validateAddress(WALLET_ADDRESS.mainnet, "testnet"); + expect(isValidAddress).toBeFalsy(); + }); + + it("should be invalid when a Testnet address is used on Mainnet network", () => { + const isValidAddress = validateAddress(WALLET_ADDRESS.testnet, "mainnet"); + expect(isValidAddress).toBeFalsy(); + }); + + it("should be invalid when a Regtest address is used on Mainnet network", () => { + const isValidAddress = validateAddress(WALLET_ADDRESS.regtest, "mainnet"); + expect(isValidAddress).toBeFalsy(); + }); +}); diff --git a/walletkit/walletkit-core/api/balance.ts b/walletkit/walletkit-core/api/balance.ts new file mode 100644 index 0000000000..ef48487a6d --- /dev/null +++ b/walletkit/walletkit-core/api/balance.ts @@ -0,0 +1,35 @@ +import { WhaleApiClient } from "@defichain/whale-api-client"; +import BigNumber from "bignumber.js"; + +interface CheckBalanceProps { + client: WhaleApiClient; + address: string; + token: string; + amount: string; +} + +/** + * Checks if wallet address has enough balance for specific token and amount. + * @param {WhaleApiClient} client instance of whale API client + * @param {string} address bech32/legacy/b58 formatted address + * @param {string} token symbol to check balance from + * @param {string} amount to check across available balance + * @returns {boolean} + */ +export async function checkSufficientBalance({ + client, + address, + token, + amount, +}: CheckBalanceProps): Promise { + if (new BigNumber(amount).isNaN()) { + throw new Error("amount should be a number"); + } + if (new BigNumber(amount).lte(0)) { + throw new Error("amount should greater than zero"); + } + const tokens = await client.address.listToken(address); + const tokenInfo = tokens.find((t) => t.symbol === token); + const availableAmount = new BigNumber(tokenInfo?.amount ?? 0); + return availableAmount.gte(amount); +} diff --git a/walletkit/walletkit-core/api/balance.unit.ts b/walletkit/walletkit-core/api/balance.unit.ts new file mode 100644 index 0000000000..6c43ca10cf --- /dev/null +++ b/walletkit/walletkit-core/api/balance.unit.ts @@ -0,0 +1,106 @@ +import { WhaleApiClient } from "@defichain/whale-api-client"; + +import { checkSufficientBalance } from "./balance"; +import { EnvironmentNetwork } from "./environment"; +import { newOceanOptions, newWhaleAPIClient } from "./whale"; + +const mockWalletAddress = "bcrt1qh2yq58tzsh4gled7wv98mm7lndj9u5v6zyr2ge"; +const mockTokenList = [ + { + id: "2", + amount: "0.00000451", + symbol: "BTC", + symbolKey: "BTC", + name: "Bitcoin", + isDAT: true, + isLPS: false, + isLoanToken: false, + displaySymbol: "dBTC", + }, +]; + +describe("Balance checker", () => { + let client: WhaleApiClient; + + beforeAll(async () => { + client = newWhaleAPIClient( + newOceanOptions(EnvironmentNetwork.RemotePlayground), + ); + + jest + .spyOn(client.address, "listToken") + .mockResolvedValue(mockTokenList as any); + }); + + it("should verify that balance is enough when balance is EQUAL TO the given amount", async () => { + const walletToken = mockTokenList[0]; + const params = { + client, + address: mockWalletAddress, + token: walletToken.symbol, + amount: "0.00000451", + }; + const hasSufficientBalance = await checkSufficientBalance(params); + expect(hasSufficientBalance).toBeTruthy(); + expect(walletToken.amount).toStrictEqual(params.amount); + }); + + it("should verify that balance is enough when balance is GREATER THAN the given amount", async () => { + const walletToken = mockTokenList[0]; + const params = { + client, + address: mockWalletAddress, + token: walletToken.symbol, + amount: "0.00000340", + }; + const hasSufficientBalance = await checkSufficientBalance(params); + expect(hasSufficientBalance).toBeTruthy(); + expect(Number(walletToken.amount)).toBeGreaterThan(Number(params.amount)); + }); + + it("should be falsy when available balance is LESS THAN given amount", async () => { + const walletToken = mockTokenList[0]; + const params = { + client, + address: mockWalletAddress, + token: walletToken.symbol, + amount: "1.5", + }; + const hasSufficientBalance = await checkSufficientBalance(params); + expect(hasSufficientBalance).toBeFalsy(); + expect(Number(walletToken.amount)).toBeLessThan(Number(params.amount)); + }); + + it("should be falsy when given token is not on wallet at all", async () => { + const params = { + client, + address: mockWalletAddress, + token: "USDC", + amount: "0.0123", + }; + const hasSufficientBalance = await checkSufficientBalance(params); + expect(hasSufficientBalance).toBeFalsy(); + }); + + it("should not allow invalid type for amount", async () => + expect(async () => { + const params = { + client, + address: mockWalletAddress, + token: "USDC", + amount: "invalid", + }; + await checkSufficientBalance(params); + }).rejects.toThrow("amount should be a number")); + + it("should not allow amount to be 0 or less than 0", async () => + expect(async () => { + const params = { + client, + address: mockWalletAddress, + token: "USDC", + amount: "0", + }; + await checkSufficientBalance(params); + }).rejects.toThrow("amount should greater than zero")); +}); diff --git a/walletkit/walletkit-core/api/environment.ts b/walletkit/walletkit-core/api/environment.ts new file mode 100644 index 0000000000..6c2b1798db --- /dev/null +++ b/walletkit/walletkit-core/api/environment.ts @@ -0,0 +1,85 @@ +/** + * Network supported in this environment + */ +export enum EnvironmentNetwork { + LocalPlayground = "Local", + RemotePlayground = "Playground", + MainNet = "MainNet", + TestNet = "TestNet", + DevNet = "DevNet", + Changi = "Changi", +} + +export enum EnvironmentName { + Production = "Production", + Preview = "Preview", + Development = "Development", +} + +interface Environment { + name: EnvironmentName; + debug: boolean; + networks: EnvironmentNetwork[]; +} + +export const environments: Record = { + Production: { + name: EnvironmentName.Production, + debug: false, + networks: [ + EnvironmentNetwork.MainNet, + EnvironmentNetwork.TestNet, + EnvironmentNetwork.DevNet, + EnvironmentNetwork.RemotePlayground, + EnvironmentNetwork.Changi, + ], + }, + Preview: { + name: EnvironmentName.Preview, + debug: true, + networks: [ + EnvironmentNetwork.RemotePlayground, + EnvironmentNetwork.DevNet, + EnvironmentNetwork.TestNet, + EnvironmentNetwork.MainNet, + EnvironmentNetwork.Changi, + ], + }, + Development: { + name: EnvironmentName.Development, + debug: true, + networks: [ + EnvironmentNetwork.LocalPlayground, + EnvironmentNetwork.RemotePlayground, + EnvironmentNetwork.DevNet, + EnvironmentNetwork.TestNet, + EnvironmentNetwork.MainNet, + EnvironmentNetwork.Changi, + ], + }, +}; + +/** + * @return Environment of current Wallet, checked via expo release channels + */ +export function getEnvironment(channel: string): Environment { + if (channel === "production") { + return environments[EnvironmentName.Production]; + } + + if (channel.startsWith("pr-preview-") || channel === "prerelease") { + return environments[EnvironmentName.Preview]; + } + + return environments[EnvironmentName.Development]; +} + +/** + * @param {EnvironmentNetwork} network to check if it is a playground network + */ +export function isPlayground(network: EnvironmentNetwork): boolean { + return [ + EnvironmentNetwork.LocalPlayground, + EnvironmentNetwork.RemotePlayground, + ].includes(network); +} diff --git a/walletkit/walletkit-core/api/environment.unit.ts b/walletkit/walletkit-core/api/environment.unit.ts new file mode 100644 index 0000000000..6335b697ad --- /dev/null +++ b/walletkit/walletkit-core/api/environment.unit.ts @@ -0,0 +1,53 @@ +import { + EnvironmentName, + EnvironmentNetwork, + environments, + getEnvironment, + isPlayground, +} from "./environment"; + +describe("environments", () => { + it("should match Production", () => { + const env = environments.Production; + + expect(env.name).toStrictEqual(EnvironmentName.Production); + }); + + it("should match Preview", () => { + const env = environments.Preview; + + expect(env.name).toStrictEqual(EnvironmentName.Preview); + }); + + it("should match Development", () => { + const env = environments.Development; + + expect(env.name).toStrictEqual(EnvironmentName.Development); + }); + + it("should match development for default", () => { + const env = getEnvironment("development"); + expect(env.name).toStrictEqual(EnvironmentName.Development); + }); + + it("should match Remote Playground on Production environment", () => { + const env = getEnvironment("production"); + expect(env.name).toStrictEqual(EnvironmentName.Production); + // To be changed to MainNet on launch + expect(env.networks[0]).toStrictEqual(EnvironmentNetwork.MainNet); + }); + + it("should match Remote Playground on prerelease environment", () => { + const env = getEnvironment("prerelease"); + expect(env.name).toStrictEqual(EnvironmentName.Preview); + expect(env.networks[0]).toStrictEqual(EnvironmentNetwork.RemotePlayground); + }); + + it("should check if isPlayground", () => { + expect(isPlayground(EnvironmentNetwork.LocalPlayground)).toBe(true); + expect(isPlayground(EnvironmentNetwork.RemotePlayground)).toBe(true); + expect(isPlayground(EnvironmentNetwork.MainNet)).toBe(false); + expect(isPlayground(EnvironmentNetwork.TestNet)).toBe(false); + expect(isPlayground(EnvironmentNetwork.Changi)).toBe(false); + }); +}); diff --git a/walletkit/walletkit-core/api/index.ts b/walletkit/walletkit-core/api/index.ts new file mode 100644 index 0000000000..d807702511 --- /dev/null +++ b/walletkit/walletkit-core/api/index.ts @@ -0,0 +1,8 @@ +export * from "./address"; +export * from "./addressValidator"; +export * from "./balance"; +export * from "./environment"; +export * from "./network"; +export * from "./paginatedAPI"; +export * from "./playground"; +export * from "./whale"; diff --git a/walletkit/walletkit-core/api/network.ts b/walletkit/walletkit-core/api/network.ts new file mode 100644 index 0000000000..9668f99661 --- /dev/null +++ b/walletkit/walletkit-core/api/network.ts @@ -0,0 +1,39 @@ +import { + Changi, + DevNet, + MainNet, + Network, + RegTest, + TestNet, +} from "@defichain/jellyfish-network"; +import { Bip32Options } from "@defichain/jellyfish-wallet-mnemonic"; + +import { EnvironmentNetwork } from "./environment"; + +export function getJellyfishNetwork(network: EnvironmentNetwork): Network { + switch (network) { + case EnvironmentNetwork.MainNet: + return MainNet; + case EnvironmentNetwork.TestNet: + return TestNet; + case EnvironmentNetwork.DevNet: + return DevNet; + case EnvironmentNetwork.Changi: + return Changi; + case EnvironmentNetwork.LocalPlayground: + case EnvironmentNetwork.RemotePlayground: + default: + return RegTest; + } +} + +export function getBip32Option(envNetwork: EnvironmentNetwork): Bip32Options { + const network = getJellyfishNetwork(envNetwork); + return { + bip32: { + public: network.bip32.publicPrefix, + private: network.bip32.privatePrefix, + }, + wif: network.wifPrefix, + }; +} diff --git a/walletkit/walletkit-core/api/network.unit.ts b/walletkit/walletkit-core/api/network.unit.ts new file mode 100644 index 0000000000..f707566ae9 --- /dev/null +++ b/walletkit/walletkit-core/api/network.unit.ts @@ -0,0 +1,29 @@ +import { EnvironmentNetwork } from "./environment"; +import { getBip32Option } from "./network"; + +describe("network", () => { + it("should resolve bip32 option for MainNet", () => { + const bip32Options = getBip32Option(EnvironmentNetwork.MainNet); + expect(bip32Options).toMatchSnapshot(); + }); + + it("should resolve bip32 option for TestNet", () => { + const bip32Options = getBip32Option(EnvironmentNetwork.TestNet); + expect(bip32Options).toMatchSnapshot(); + }); + + it("should resolve bip32 option for LocalPlayground", () => { + const bip32Options = getBip32Option(EnvironmentNetwork.LocalPlayground); + expect(bip32Options).toMatchSnapshot(); + }); + + it("should resolve bip32 option for RemotePlayground", () => { + const bip32Options = getBip32Option(EnvironmentNetwork.RemotePlayground); + expect(bip32Options).toMatchSnapshot(); + }); + + it("should resolve bip32 option for Changi", () => { + const bip32Options = getBip32Option(EnvironmentNetwork.Changi); + expect(bip32Options).toMatchSnapshot(); + }); +}); diff --git a/walletkit/walletkit-core/api/paginatedAPI.ts b/walletkit/walletkit-core/api/paginatedAPI.ts new file mode 100644 index 0000000000..7d37ac21d2 --- /dev/null +++ b/walletkit/walletkit-core/api/paginatedAPI.ts @@ -0,0 +1,22 @@ +import { ApiPagedResponse } from "@defichain/whale-api-client"; + +export async function getPaginatedResponse( + api: (limit: number, next?: string) => Promise>, +): Promise { + const current = []; + let hasNext = false; + let next; + + try { + do { + // eslint-disable-next-line no-await-in-loop + const data: ApiPagedResponse = await api(200, next); + current.push(...data); + hasNext = data.hasNext; + next = data.nextToken; + } while (hasNext); + } catch (e) { + return current; + } + return current; +} diff --git a/walletkit/walletkit-core/api/paginatedAPI.unit.ts b/walletkit/walletkit-core/api/paginatedAPI.unit.ts new file mode 100644 index 0000000000..1a4d515402 --- /dev/null +++ b/walletkit/walletkit-core/api/paginatedAPI.unit.ts @@ -0,0 +1,12 @@ +import { getPaginatedResponse } from "./paginatedAPI"; + +describe("Paginated API", () => { + it("should receive correct value", async () => { + const sampleData = [{ name: "John" }]; + const mockAPI = jest.fn().mockResolvedValue(sampleData); + const response = await getPaginatedResponse((limit, next) => + mockAPI(limit, next), + ); + expect(response).toEqual(sampleData); + }); +}); diff --git a/walletkit/walletkit-core/api/playground.ts b/walletkit/walletkit-core/api/playground.ts new file mode 100644 index 0000000000..b498d83fda --- /dev/null +++ b/walletkit/walletkit-core/api/playground.ts @@ -0,0 +1,20 @@ +import { PlaygroundApiClient } from "@defichain/playground-api-client"; + +import { EnvironmentNetwork } from "./environment"; +import { getDefaultDefiChainURL } from "./whale"; + +export function newPlaygroundClient( + network: EnvironmentNetwork, +): PlaygroundApiClient { + const url = getDefaultDefiChainURL(network); + switch (network) { + case EnvironmentNetwork.RemotePlayground: + return new PlaygroundApiClient({ + url, + }); + case EnvironmentNetwork.LocalPlayground: + return new PlaygroundApiClient({ url }); + default: + throw new Error(`playground not available for '${network}'`); + } +} diff --git a/walletkit/walletkit-core/api/whale.ts b/walletkit/walletkit-core/api/whale.ts new file mode 100644 index 0000000000..6ae429afbc --- /dev/null +++ b/walletkit/walletkit-core/api/whale.ts @@ -0,0 +1,72 @@ +import { + WhaleApiClient, + WhaleApiClientOptions, + WhaleRpcClient, +} from "@defichain/whale-api-client"; + +import { EnvironmentNetwork } from "./environment"; + +export function newOceanOptions( + network: EnvironmentNetwork, + url?: string, +): WhaleApiClientOptions { + switch (network) { + case EnvironmentNetwork.LocalPlayground: + return { + url: url ?? "http://localhost:19553", + network: "regtest", + version: "v0", + }; + case EnvironmentNetwork.RemotePlayground: + return { + url: url ?? "https://playground.jellyfishsdk.com", + network: "regtest", + version: "v0", + }; + case EnvironmentNetwork.TestNet: + return { + url: url ?? "https://testnet.ocean.jellyfishsdk.com", + network: "testnet", + version: "v0", + }; + case EnvironmentNetwork.DevNet: + return { + url: url ?? "http://devnet.ocean.jellyfishsdk.com", + network: "devnet", + version: "v0", + }; + case EnvironmentNetwork.Changi: + return { + url: url ?? "https://changi.ocean.jellyfishsdk.com", + network: "changi", + version: "v0", + }; + case EnvironmentNetwork.MainNet: + default: + return { + url: url ?? "http://34.143.176.39:3002", + // url: url ?? "https://ocean.defichain.com", + network: "mainnet", + version: "v0", + }; + } +} + +export function newWhaleAPIClient( + options: WhaleApiClientOptions, +): WhaleApiClient { + return new WhaleApiClient(options); +} + +export function newWhaleRpcClient( + options: WhaleApiClientOptions, +): WhaleRpcClient { + return new WhaleRpcClient( + `${options.url}/${options.version}/${options.network}/rpc`, + ); +} + +export function getDefaultDefiChainURL(network: EnvironmentNetwork): string { + const { url } = newOceanOptions(network); + return url as string; +} diff --git a/walletkit/walletkit-core/api/whale.unit.ts b/walletkit/walletkit-core/api/whale.unit.ts new file mode 100644 index 0000000000..73e20fb97b --- /dev/null +++ b/walletkit/walletkit-core/api/whale.unit.ts @@ -0,0 +1,173 @@ +import { EnvironmentNetwork } from "./environment"; +import { + getDefaultDefiChainURL, + newOceanOptions, + newWhaleAPIClient, + newWhaleRpcClient, +} from "./whale"; + +describe("whale", () => { + it("should match ocean options for local playground", () => { + const oceanOptions = newOceanOptions(EnvironmentNetwork.LocalPlayground); + expect(oceanOptions).toMatchObject({ + url: "http://localhost:19553", + network: "regtest", + version: "v0", + }); + }); + + it("should match ocean options for remote playground", () => { + const oceanOptions = newOceanOptions(EnvironmentNetwork.RemotePlayground); + expect(oceanOptions).toMatchObject({ + url: "https://playground.jellyfishsdk.com", + network: "regtest", + version: "v0", + }); + }); + + it("should match ocean options for testnet", () => { + const oceanOptions = newOceanOptions(EnvironmentNetwork.TestNet); + expect(oceanOptions).toMatchObject({ + url: "https://testnet.ocean.jellyfishsdk.com", + network: "testnet", + version: "v0", + }); + }); + + it("should match ocean options for mainnet", () => { + const oceanOptions = newOceanOptions(EnvironmentNetwork.MainNet); + expect(oceanOptions).toMatchObject({ + url: "https://ocean.defichain.com", + network: "mainnet", + version: "v0", + }); + }); + + it("should match ocean options for devnet", () => { + const oceanOptions = newOceanOptions(EnvironmentNetwork.DevNet); + expect(oceanOptions).toMatchObject({ + url: "http://devnet.ocean.jellyfishsdk.com", + network: "devnet", + version: "v0", + }); + }); + + it("should match ocean options for changi", () => { + const oceanOptions = newOceanOptions(EnvironmentNetwork.Changi); + expect(oceanOptions).toMatchObject({ + url: "https://changi.ocean.jellyfishsdk.com", + network: "changi", + version: "v0", + }); + }); + + it("should create new instance of whale api client", () => { + const oceanOptions = newOceanOptions(EnvironmentNetwork.TestNet); + const whaleApiClient = newWhaleAPIClient(oceanOptions); + expect(whaleApiClient).toBeDefined(); + }); + + it("should create new instance of whale rpc client", () => { + const oceanOptions = newOceanOptions(EnvironmentNetwork.TestNet); + const whaleApiClient = newWhaleRpcClient(oceanOptions); + expect(whaleApiClient).toBeDefined(); + }); + + it("should match default ocean url for local playground", () => { + const defaultURL = getDefaultDefiChainURL( + EnvironmentNetwork.LocalPlayground, + ); + expect(defaultURL).toStrictEqual("http://localhost:19553"); + }); + + it("should match default ocean url for remote playground", () => { + const defaultURL = getDefaultDefiChainURL( + EnvironmentNetwork.RemotePlayground, + ); + expect(defaultURL).toStrictEqual("https://playground.jellyfishsdk.com"); + }); + + it("should match default ocean url for testnet", () => { + const defaultURL = getDefaultDefiChainURL(EnvironmentNetwork.TestNet); + expect(defaultURL).toStrictEqual("https://testnet.ocean.jellyfishsdk.com"); + }); + + it("should match default ocean url for mainnet", () => { + const defaultURL = getDefaultDefiChainURL(EnvironmentNetwork.MainNet); + expect(defaultURL).toStrictEqual("https://ocean.defichain.com"); + }); + + it("should match default ocean url for devnet", () => { + const defaultURL = getDefaultDefiChainURL(EnvironmentNetwork.DevNet); + expect(defaultURL).toStrictEqual("http://devnet.ocean.jellyfishsdk.com"); + }); + + it("should match default ocean url for changi", () => { + const defaultURL = getDefaultDefiChainURL(EnvironmentNetwork.Changi); + expect(defaultURL).toStrictEqual("https://changi.ocean.jellyfishsdk.com"); + }); +}); + +describe("whale custom provider", () => { + const customProviderURL = "https://custom.provider.test.com"; + + it("should match custom provider URL for local playground", () => { + const oceanOptions = newOceanOptions( + EnvironmentNetwork.LocalPlayground, + customProviderURL, + ); + expect(oceanOptions).toMatchObject({ + url: customProviderURL, + network: "regtest", + version: "v0", + }); + }); + + it("should match custom provider URL for testnet", () => { + const oceanOptions = newOceanOptions( + EnvironmentNetwork.TestNet, + customProviderURL, + ); + expect(oceanOptions).toMatchObject({ + url: customProviderURL, + network: "testnet", + version: "v0", + }); + }); + + it("should match custom provider URL for mainnet", () => { + const oceanOptions = newOceanOptions( + EnvironmentNetwork.MainNet, + customProviderURL, + ); + expect(oceanOptions).toMatchObject({ + url: customProviderURL, + network: "mainnet", + version: "v0", + }); + }); + + it("should match custom provider URL for devnet", () => { + const oceanOptions = newOceanOptions( + EnvironmentNetwork.DevNet, + customProviderURL, + ); + expect(oceanOptions).toMatchObject({ + url: customProviderURL, + network: "devnet", + version: "v0", + }); + }); + + it("should match custom provider URL for changi", () => { + const oceanOptions = newOceanOptions( + EnvironmentNetwork.Changi, + customProviderURL, + ); + expect(oceanOptions).toMatchObject({ + url: customProviderURL, + network: "changi", + version: "v0", + }); + }); +}); diff --git a/walletkit/walletkit-core/index.ts b/walletkit/walletkit-core/index.ts new file mode 100644 index 0000000000..5b45c890f3 --- /dev/null +++ b/walletkit/walletkit-core/index.ts @@ -0,0 +1,2 @@ +export * from "./api"; +export * from "./website"; diff --git a/walletkit/walletkit-core/website/index.ts b/walletkit/walletkit-core/website/index.ts new file mode 100644 index 0000000000..9c22a265c7 --- /dev/null +++ b/walletkit/walletkit-core/website/index.ts @@ -0,0 +1 @@ +export * from "./website"; diff --git a/walletkit/walletkit-core/website/website.ts b/walletkit/walletkit-core/website/website.ts new file mode 100644 index 0000000000..e2f5513e7a --- /dev/null +++ b/walletkit/walletkit-core/website/website.ts @@ -0,0 +1,147 @@ +import { EnvironmentNetwork } from "../api/environment"; + +export interface AnnouncementText { + en: string; + de: string; + "zh-Hans": string; + "zh-Hant": string; + fr?: string; + es: string; + it: string; +} + +export interface AnnouncementData { + lang: AnnouncementText; + /** + * Versioned matching represented as semver satisfies + */ + version: string; + url?: { + ios: string; + android: string; + macos: string; + windows: string; + web: string; + }; + /** + * `id` will be stored in device's persistence storage. Therefore, each announcement's `id` should be unique string to enable close announcement function + */ + id?: string; + type: "EMERGENCY" | "OTHER_ANNOUNCEMENT" | "OUTAGE" | "SCAN"; +} + +export interface FeatureFlag { + id: FeatureFlagID; + name: string; + version: string; + stage: FeatureFlagStage; + description: string; + networks: EnvironmentNetwork[]; + platforms: Platform[]; + app: App[]; +} + +export interface DeFiChainStatus { + page?: { + id: string; + name: string; + url: string; + updated_at: string; + }; + status: { + description: "operational" | "outage"; + indicator: string; + }; + components?: Array<{ + created_at: string; + description?: string; + id: string; + name: string; + page_id: string; + position: number; + status: string; + updated_at: string; + }>; + incidents?: Array<{ + created_at: string; + id: string; + impact: string; + incident_updates: Array<{ + body: string; + created_at: string; + display_at: string; + id: string; + incident_id: string; + status: string; + updated_at: string; + }>; + monitoring_at?: string; + name: string; + page_id?: string; + resolved_at?: string; + shortlink: string; + status: string; + updated_at: string; + }>; + scheduled_maintenances: Array<{ + created_at: string; + id: string; + impact: string; + incident_updates: Array<{ + body: string; + created_at: string; + display_at: string; + id: string; + incident_id: string; + status: string; + updated_at: string; + }>; + monitoring_at?: string; + name: string; + page_id: string; + resolved_at?: string; + scheduled_for: string; + scheduled_until: string; + shortlink: string; + status: "Scheduled" | "In Progress" | "Verifying" | "Completed"; + updated_at: string; + }>; +} + +export interface PoolpairWithStabInfo { + pairDisplaySymbol: string; + tokenADisplaySymbol: string; + tokenBDisplaySymbol: string; + dexStabilizationFee: string; +} + +export type Platform = "ios" | "android" | "windows" | "macos" | "web"; + +export type App = "MOBILE_LW" | "DESKTOP_LW" | "SCAN"; + +export type FeatureFlagID = + | "loan" + | "auction" + | "dfi_loan_payment" + | "local_storage" + | "dusd_vault_share" + | "dusd_loan_payment" + | "future_swap" + | "service_provider" + | "onboarding_v2" + | "dusd_dex_high_fee" + | "dusd_dfi_high_fee" + | "setting_v2" + | "portfolio_v2" + | "add_liquidity_v2" + | "remove_liquidity_v2" + | "send_v2" + | "composite_swap_v2" + | "unloop_dusd" + | "ocg_cfp_dfip" + | "evm" + | "loop_dusd" + | "save_tx"; + +// Stages of feature flag +export type FeatureFlagStage = "alpha" | "beta" | "public"; diff --git a/walletkit/walletkit-core/website/website.unit.ts b/walletkit/walletkit-core/website/website.unit.ts new file mode 100644 index 0000000000..859504fb2a --- /dev/null +++ b/walletkit/walletkit-core/website/website.unit.ts @@ -0,0 +1,22 @@ +import { AnnouncementText } from "./website"; + +describe("website", () => { + it("should check types of AnnouncementText", () => { + const announcement: AnnouncementText = { + en: "Good morning", + it: "Buon giorno", + "zh-Hans": "Good morning", + fr: "Good morning", + es: "Good morning", + de: "Good morning", + "zh-Hant": "Good morning", + }; + expect(typeof announcement.en).toBe("string"); + expect(typeof announcement.it).toBe("string"); + expect(typeof announcement["zh-Hant"]).toBe("string"); + expect(typeof announcement["zh-Hans"]).toBe("string"); + expect(typeof announcement.fr).toBe("string"); + expect(typeof announcement.es).toBe("string"); + expect(typeof announcement.de).toBe("string"); + }); +}); diff --git a/walletkit/walletkit-testcontainers/DeFiChainStubContainer.ts b/walletkit/walletkit-testcontainers/DeFiChainStubContainer.ts new file mode 100644 index 0000000000..0b8f9750ae --- /dev/null +++ b/walletkit/walletkit-testcontainers/DeFiChainStubContainer.ts @@ -0,0 +1,81 @@ +import { + PlaygroundApiClient, + PlaygroundRpcClient, +} from "@defichain/playground-api-client"; +import { + NativeChainContainer, + PlaygroundApiContainer, + StartedNativeChainContainer, + StartedPlaygroundApiContainer, + StartedWhaleApiContainer, + WhaleApiContainer, +} from "@defichain/testcontainers"; +import { WhaleApiClient } from "@defichain/whale-api-client"; +import { Network } from "testcontainers"; + +/** + * DeFiChain Container that runs all necessary containers (Playground, Whale, Ain). + * + * */ +export class DeFiChainStubContainer { + async start(): Promise { + const network = await new Network().start(); + const defid = await new NativeChainContainer() + .withNetwork(network) + .withPreconfiguredRegtestMasternode() + .start(); + const whale = await new WhaleApiContainer() + .withNetwork(network) + .withNativeChain(defid, network) + .start(); + const playground = await new PlaygroundApiContainer() + .withNetwork(network) + .withNativeChain(defid, network) + .start(); + await playground.waitForReady(); + return new StartedDeFiChainStubContainer(defid, whale, playground); + } +} + +export class StartedDeFiChainStubContainer { + public playgroundRpcClient: PlaygroundRpcClient; + + public playgroundClient: PlaygroundApiClient; + + public whaleClient: WhaleApiClient; + + public static LOCAL_MNEMONIC = + "avoid between cupboard there nerve sugar quote foot broom intact seminar culture much anger hold rival moral silly volcano fog service decline tortoise combine"; + + constructor( + protected defid: StartedNativeChainContainer, + protected whale: StartedWhaleApiContainer, + protected playground: StartedPlaygroundApiContainer, + ) { + this.playgroundClient = new PlaygroundApiClient({ + url: this.playground.getPlaygroundApiClientOptions().url, + }); + this.playgroundRpcClient = new PlaygroundRpcClient(this.playgroundClient); + this.whaleClient = new WhaleApiClient( + this.whale.getWhaleApiClientOptions(), + ); + } + + async stop(): Promise { + await this.whale.stop(); + await this.defid.stop(); + await this.playground.stop(); + } + + async generateBlock(): Promise { + await this.playgroundClient.rpc.call( + "generatetoaddress", + [10, "mswsMVsyGMj1FzDMbbxw2QW3KvQAv2FKiy"], + "number", + ); + } + + async getWhaleURL(): Promise { + return this.whale.getWhaleApiClientOptions().url; + } +} diff --git a/walletkit/walletkit-testcontainers/DeFiChainStubContainer.unit.ts b/walletkit/walletkit-testcontainers/DeFiChainStubContainer.unit.ts new file mode 100644 index 0000000000..379864a411 --- /dev/null +++ b/walletkit/walletkit-testcontainers/DeFiChainStubContainer.unit.ts @@ -0,0 +1,8 @@ +import { DeFiChainStubContainer } from "./DeFiChainStubContainer"; + +describe("testcontainers initialize", () => { + it("should initialize containers", async () => { + const container = new DeFiChainStubContainer(); + expect(container instanceof DeFiChainStubContainer).toBe(true); + }); +}); diff --git a/walletkit/walletkit-testcontainers/index.ts b/walletkit/walletkit-testcontainers/index.ts new file mode 100644 index 0000000000..9cf9907fad --- /dev/null +++ b/walletkit/walletkit-testcontainers/index.ts @@ -0,0 +1 @@ +export * from "./DeFiChainStubContainer"; diff --git a/walletkit/walletkit-ui/contexts/DeFiScanContext.tsx b/walletkit/walletkit-ui/contexts/DeFiScanContext.tsx new file mode 100644 index 0000000000..e3b7e75460 --- /dev/null +++ b/walletkit/walletkit-ui/contexts/DeFiScanContext.tsx @@ -0,0 +1,101 @@ +import { EnvironmentNetwork } from "@waveshq/walletkit-core"; +import React, { createContext, useContext, useMemo } from "react"; + +import { useNetworkContext } from "./NetworkContext"; + +interface DeFiScanContextI { + getTransactionUrl: (txid: string, rawtx?: string) => string; + getBlocksUrl: (blockCount: number) => string; + getTokenUrl: (tokenId: number | string) => string; + getAddressUrl: (address: string) => string; + getVaultsUrl: (vaultId: string) => string; + getAuctionsUrl: (vaultId: string, index: number) => string; + getBlocksCountdownUrl: (blockCount: number) => string; +} + +const DeFiScanContext = createContext(undefined as any); +const baseDefiScanUrl = "https://defiscan.live"; + +export function useDeFiScanContext(): DeFiScanContextI { + return useContext(DeFiScanContext); +} + +function getNetworkParams(network: EnvironmentNetwork): string { + switch (network) { + case EnvironmentNetwork.MainNet: + // no-op: network param not required for MainNet + return ""; + case EnvironmentNetwork.TestNet: + return `?network=${EnvironmentNetwork.TestNet}`; + case EnvironmentNetwork.DevNet: + return `?network=${EnvironmentNetwork.DevNet}`; + case EnvironmentNetwork.Changi: + return `?network=${EnvironmentNetwork.Changi}`; + case EnvironmentNetwork.LocalPlayground: + case EnvironmentNetwork.RemotePlayground: + return `?network=${EnvironmentNetwork.RemotePlayground}`; + default: + return ""; + } +} + +export function getURLByNetwork( + path: string, + network: EnvironmentNetwork, + id: number | string, +): string { + return `${baseDefiScanUrl}/${path}/${id}${getNetworkParams(network)}`; +} + +export function getTxURLByNetwork( + network: EnvironmentNetwork, + txid: string, + rawtx?: string, +): string { + let baseUrl = `${baseDefiScanUrl}/transactions/${txid}`; + + baseUrl += getNetworkParams(network); + + if (typeof rawtx === "string" && rawtx.length !== 0) { + if (network === EnvironmentNetwork.MainNet) { + baseUrl += `?rawtx=${rawtx}`; + } else { + baseUrl += `&rawtx=${rawtx}`; + } + } + + return baseUrl; +} + +export function DeFiScanProvider( + props: React.PropsWithChildren, +): JSX.Element | null { + const { network } = useNetworkContext(); + const { children } = props; + + const context: DeFiScanContextI = useMemo( + () => ({ + getTransactionUrl: (txid: string, rawtx?: string): string => + getTxURLByNetwork(network, txid, rawtx), + getBlocksUrl: (blockCount: number) => + getURLByNetwork("blocks", network, blockCount), + getTokenUrl: (tokenId: number | string) => + getURLByNetwork("tokens", network, tokenId), + getAddressUrl: (address: string) => + getURLByNetwork("address", network, address), + getVaultsUrl: (vaultId: string) => + getURLByNetwork("vaults", network, vaultId), + getAuctionsUrl: (vaultId: string, index: number) => + getURLByNetwork(`vaults/${vaultId}/auctions`, network, index), + getBlocksCountdownUrl: (blockCount: number) => + getURLByNetwork("blocks/countdown", network, blockCount), + }), + [network], + ); + + return ( + + {children} + + ); +} diff --git a/walletkit/walletkit-ui/contexts/DisplayBalanceContext.tsx b/walletkit/walletkit-ui/contexts/DisplayBalanceContext.tsx new file mode 100644 index 0000000000..91df2929b4 --- /dev/null +++ b/walletkit/walletkit-ui/contexts/DisplayBalanceContext.tsx @@ -0,0 +1,69 @@ +import React, { createContext, useContext, useEffect, useState } from "react"; + +import { BaseLogger } from "./logger"; + +const HIDDEN_BALANCE_TEXT = "*****"; + +interface DisplayBalancesProps { + isBalancesDisplayed: boolean; + hiddenBalanceText: string; + toggleDisplayBalances: () => Promise; +} + +const DisplayBalancesContext = createContext( + undefined as any, +); + +/** + * DisplayBalancesContext Context wrapped within + * + * This context enables display/hide of balances management across the app + */ + +export function useDisplayBalancesContext(): DisplayBalancesProps { + return useContext(DisplayBalancesContext); +} + +interface DisplayBalancesPersistenceProps { + set(isBalancesDisplayed: boolean): Promise; + get(): Promise; +} + +interface DisplayBalancesProviderProps { + logger: BaseLogger; + DisplayBalancesPersistence: DisplayBalancesPersistenceProps; +} + +export function DisplayBalancesProvider( + props: React.PropsWithChildren, +): JSX.Element | null { + const { logger, DisplayBalancesPersistence, children } = props; + const [isBalancesDisplayed, setIsBalancesDisplayed] = useState(true); + const toggleDisplayBalances = async (): Promise => { + setIsBalancesDisplayed(!isBalancesDisplayed); + await DisplayBalancesPersistence.set(!isBalancesDisplayed).catch((err) => + logger.error(err), + ); + }; + + // eslint-disable-next-line react/jsx-no-constructed-context-values + const context: DisplayBalancesProps = { + hiddenBalanceText: HIDDEN_BALANCE_TEXT, + isBalancesDisplayed, + toggleDisplayBalances, + }; + + useEffect(() => { + DisplayBalancesPersistence.get() + .then((b) => { + setIsBalancesDisplayed(b); + }) + .catch(logger.error); + }, []); + + return ( + + {children} + + ); +} diff --git a/walletkit/walletkit-ui/contexts/LanguageProvider.test.tsx b/walletkit/walletkit-ui/contexts/LanguageProvider.test.tsx new file mode 100644 index 0000000000..7d20a2afef --- /dev/null +++ b/walletkit/walletkit-ui/contexts/LanguageProvider.test.tsx @@ -0,0 +1,93 @@ +/** + * @jest-environment jsdom + */ + +import { render } from "@testing-library/react"; +import { renderHook } from "@testing-library/react-hooks"; +import React from "react"; + +import { + LanguageProvider, + useLanguage, + useLanguageContext, +} from "./LanguageProvider"; + +const consoleLog = jest.spyOn(console, "log").mockImplementation(jest.fn); +const consoleError = jest.spyOn(console, "error").mockImplementation(jest.fn); +const logger = { error: () => consoleError, info: () => consoleLog }; +const onChangeLocale = jest.fn(); + +describe("useLanguage hook test", () => { + it("should pass when it uses users devices locale on first app install", async () => { + const api = { + set: jest.fn(), + get: async () => null, + }; + const desiredLanguage = "fr"; + const { result, waitForNextUpdate } = renderHook(() => + useLanguage({ + api, + locale: desiredLanguage, + logger, + onChangeLocale, + }), + ); + await waitForNextUpdate(); + expect(result.current.language).toBe(desiredLanguage); + expect(result.current.isLanguageLoaded).toBe(true); + }); + + it("should pass when use already selected language", async () => { + const desiredLanguage = "fr"; + const api = { + set: jest.fn(), + get: async () => desiredLanguage, + }; + const { result, waitForNextUpdate } = renderHook(() => + useLanguage({ api, locale: "en", logger, onChangeLocale }), + ); + await waitForNextUpdate(); + expect(result.current.language).toBe(desiredLanguage); + expect(result.current.isLanguageLoaded).toBe(true); + }); + + it("should pass when no language is selected or dont find any language on users device", async () => { + const api = { + set: jest.fn(), + get: async () => null, + }; + const { result, waitForNextUpdate } = renderHook(() => + useLanguage({ api, logger, onChangeLocale }), + ); + await waitForNextUpdate(); + expect(result.current.language).toBe("en"); + expect(result.current.isLanguageLoaded).toBe(true); + }); +}); + +describe("LanguageProvider Context test", () => { + it("should match snapshot", async () => { + function ThemeProviderComponent(): JSX.Element { + const { language } = useLanguageContext(); + return ( +
+ {language} +
+ ); + } + const api = { + set: jest.fn(), + get: async () => "fr", + }; + const rendered = render( + + + , + ); + expect(rendered).toMatchSnapshot(); + }); +}); diff --git a/walletkit/walletkit-ui/contexts/LanguageProvider.tsx b/walletkit/walletkit-ui/contexts/LanguageProvider.tsx new file mode 100644 index 0000000000..01a6f65db3 --- /dev/null +++ b/walletkit/walletkit-ui/contexts/LanguageProvider.tsx @@ -0,0 +1,137 @@ +import "dayjs/locale/de"; +import "dayjs/locale/en"; +import "dayjs/locale/fr"; +import "dayjs/locale/zh"; +import "dayjs/locale/es"; +import "dayjs/locale/it"; + +import dayjs from "dayjs"; +import localizedFormat from "dayjs/plugin/localizedFormat"; +import React, { + createContext, + PropsWithChildren, + useContext, + useEffect, + useState, +} from "react"; + +import { BaseLogger } from "./logger"; + +dayjs.extend(localizedFormat); + +interface LanguageLoader { + isLanguageLoaded: boolean; + language: NonNullable; +} + +interface LanguageContextI { + api: { + get: () => Promise; + set: (language: NonNullable) => Promise; + }; + locale?: string; + logger: BaseLogger; + onChangeLocale: (locale: string) => void; +} + +export function useLanguage({ + api, + locale, + logger, + onChangeLocale, +}: LanguageContextI): LanguageLoader { + const defaultLanguage = "en"; + const [isLanguageLoaded, setIsLanguageLoaded] = useState(false); + const [language, setLanguage] = + useState>(defaultLanguage); + + useEffect(() => { + api + .get() + .then((l) => { + let currentLanguage: NonNullable = defaultLanguage; + if (l !== null && l !== undefined) { + currentLanguage = l; + } else if (locale !== null && locale !== undefined) { + currentLanguage = locale; // use device's locale on first app install + } + setLanguage(currentLanguage); + }) + .catch((err) => logger.error(err)) + .finally(() => setIsLanguageLoaded(true)); + }, []); + + useEffect(() => { + onChangeLocale(language); + }, [language]); + + return { + isLanguageLoaded, + language, + }; +} + +interface Language { + language: NonNullable; + setLanguage: (language: NonNullable) => Promise; +} + +const LanguageContext = createContext(undefined as any); + +export function useLanguageContext(): Language { + return useContext(LanguageContext); +} + +export function LanguageProvider( + props: LanguageContextI & PropsWithChildren, +): JSX.Element | null { + const { api, children, locale, logger, onChangeLocale } = props; + const { language } = useLanguage({ api, locale, logger, onChangeLocale }); + const [currentLanguage, setCurrentLanguage] = + useState>(language); + + useEffect(() => { + setCurrentLanguage(language); + }, [language]); + + useEffect(() => { + onChangeLocale(currentLanguage); + switch (currentLanguage) { + case "de": + dayjs.locale("de"); + break; + case "fr": + dayjs.locale("fr"); + break; + case "zh-Hans": + case "zh-Hant": + dayjs.locale("zh"); + break; + case "es": + dayjs.locale("es"); + break; + case "it": + dayjs.locale("it"); + break; + default: + dayjs.locale("en"); + } + }, [currentLanguage]); + + const setLanguage = async (newLocale: string): Promise => { + setCurrentLanguage(newLocale); + await api.set(newLocale); + }; + + // eslint-disable-next-line react/jsx-no-constructed-context-values + const context: Language = { + language: currentLanguage, + setLanguage, + }; + + return ( + + {children} + + ); +} diff --git a/walletkit/walletkit-ui/contexts/NetworkContext.tsx b/walletkit/walletkit-ui/contexts/NetworkContext.tsx new file mode 100644 index 0000000000..dda0764716 --- /dev/null +++ b/walletkit/walletkit-ui/contexts/NetworkContext.tsx @@ -0,0 +1,73 @@ +import { NetworkName } from "@defichain/jellyfish-network"; +import { + EnvironmentNetwork, + getJellyfishNetwork, +} from "@waveshq/walletkit-core"; +import React, { + createContext, + PropsWithChildren, + useContext, + useEffect, + useState, +} from "react"; + +import { BaseLogger } from "./logger"; + +interface NetworkContextI { + network: EnvironmentNetwork; + networkName: NetworkName; + updateNetwork: (network: EnvironmentNetwork) => Promise; +} + +const NetworkContext = createContext(undefined as any); + +export function useNetworkContext(): NetworkContextI { + return useContext(NetworkContext); +} + +export interface NetworkProviderProps extends PropsWithChildren<{}> { + api: { + getNetwork: () => Promise; + setNetwork: (network: EnvironmentNetwork) => Promise; + }; + logger: BaseLogger; +} + +export function NetworkProvider( + props: NetworkProviderProps, +): JSX.Element | null { + const [network, setNetwork] = useState(); + const [networkName, setNetworkName] = useState(); + const { api, logger, children } = props; + + useEffect(() => { + api + .getNetwork() + .then(async (value: EnvironmentNetwork) => { + setNetworkName(getJellyfishNetwork(value).name); + setNetwork(value); + }) + .catch(logger.error); + }, []); + + if (network === undefined || networkName === undefined) { + return null; + } + + // eslint-disable-next-line react/jsx-no-constructed-context-values + const context: NetworkContextI = { + network, + networkName, + async updateNetwork(value: EnvironmentNetwork): Promise { + await api.setNetwork(value); + setNetworkName(getJellyfishNetwork(value).name); + setNetwork(value); + }, + }; + + return ( + + {children} + + ); +} diff --git a/walletkit/walletkit-ui/contexts/PlaygroundContext.tsx b/walletkit/walletkit-ui/contexts/PlaygroundContext.tsx new file mode 100644 index 0000000000..d0a62857aa --- /dev/null +++ b/walletkit/walletkit-ui/contexts/PlaygroundContext.tsx @@ -0,0 +1,50 @@ +import { + PlaygroundApiClient, + PlaygroundRpcClient, +} from "@defichain/playground-api-client"; +import { isPlayground, newPlaygroundClient } from "@waveshq/walletkit-core"; +import { createContext, useContext, useMemo } from "react"; +import * as React from "react"; + +import { useNetworkContext } from "./NetworkContext"; + +interface PlaygroundContextI { + rpc: PlaygroundRpcClient; + api: PlaygroundApiClient; +} + +const PlaygroundContext = createContext( + undefined, +); + +export function usePlaygroundContext(): PlaygroundContextI { + const context = useContext(PlaygroundContext); + if (context !== undefined) { + return context; + } + + throw new Error("Playground not configured"); +} + +export function PlaygroundProvider( + props: React.PropsWithChildren, +): JSX.Element | null { + const { children } = props; + const { network } = useNetworkContext(); + + const context = useMemo(() => { + if (!isPlayground(network)) { + return undefined; + } + + const api = newPlaygroundClient(network); + const rpc = new PlaygroundRpcClient(api); + return { api, rpc }; + }, [network]); + + return ( + + {children} + + ); +} diff --git a/walletkit/walletkit-ui/contexts/StatsProvider.tsx b/walletkit/walletkit-ui/contexts/StatsProvider.tsx new file mode 100644 index 0000000000..2a7c7750f7 --- /dev/null +++ b/walletkit/walletkit-ui/contexts/StatsProvider.tsx @@ -0,0 +1,79 @@ +import { isPlayground } from "@waveshq/walletkit-core"; +import React, { PropsWithChildren, useEffect } from "react"; +import { useDispatch, useSelector } from "react-redux"; + +import { block, BlockState } from "../store"; +import { BaseLogger } from "./logger"; +import { useNetworkContext } from "./NetworkContext"; +import { useWhaleApiClient } from "./WhaleContext"; + +export interface StatsProviderProps extends PropsWithChildren<{}> { + logger: BaseLogger; +} + +export function StatsProvider(props: StatsProviderProps): JSX.Element | null { + const { logger, children } = props; + const { network } = useNetworkContext(); + const isPolling = useSelector((state: BlockState) => state.isPolling); + const api = useWhaleApiClient(); + const interval: number = isPlayground(network) ? 3000 : 30000; + + const dispatch = useDispatch(); + + useEffect(() => { + // isPolling is a good indicator of background polling + // we can use AppState to suspend and activate polling based on user activity + let intervalID: NodeJS.Timeout; + let timeoutID: NodeJS.Timeout; + + function refresh(): void { + dispatch(block.actions.setPolling(true)); + // if blockchain is connected successfully, update both lastSync & lastSuccessfulSync to current date + api.stats + .get() + .then(({ count, tvl }) => { + dispatch( + block.actions.updateBlockDetails({ + count: count.blocks, + masternodeCount: count.masternodes, + lastSync: new Date().toString(), + lastSuccessfulSync: new Date().toString(), + tvl: tvl?.dex ?? 0, + }), + ); + dispatch(block.actions.setConnected(true)); + }) + .catch((err) => { + // if blockchain is not connected successfully, only update value of lastSync to current date + dispatch( + block.actions.updateBlockDetails({ + count: 0, + masternodeCount: 0, + lastSync: new Date().toString(), + }), + ); + dispatch(block.actions.setConnected(false)); + logger.error(err); + }); + } + + if (!isPolling) { + timeoutID = setTimeout(() => { + refresh(); + intervalID = setInterval(refresh, interval); + }, 1000); + } + return () => { + dispatch(block.actions.setPolling(false)); + if (intervalID !== undefined) { + clearInterval(intervalID); + } + if (timeoutID !== undefined) { + clearTimeout(timeoutID); + } + }; + }, [api, interval, network, dispatch]); + + // eslint-disable-next-line react/jsx-no-useless-fragment + return <>{children}; +} diff --git a/walletkit/walletkit-ui/contexts/StoreProvider.tsx b/walletkit/walletkit-ui/contexts/StoreProvider.tsx new file mode 100644 index 0000000000..2e62d302a9 --- /dev/null +++ b/walletkit/walletkit-ui/contexts/StoreProvider.tsx @@ -0,0 +1,20 @@ +import { EnhancedStore } from "@reduxjs/toolkit"; +import React, { PropsWithChildren, useMemo } from "react"; +import { Provider } from "react-redux"; + +import { useWalletPersistenceContext } from "./WalletPersistenceContext"; + +interface IStoreProvider { + initializeStore: () => EnhancedStore; +} + +export function StoreProvider( + props: PropsWithChildren, +): JSX.Element { + const { children, initializeStore } = props; + const { wallets } = useWalletPersistenceContext(); + + const store = useMemo(() => initializeStore(), [wallets]); + + return {children}; +} diff --git a/walletkit/walletkit-ui/contexts/StoreServiceProvider.tsx b/walletkit/walletkit-ui/contexts/StoreServiceProvider.tsx new file mode 100644 index 0000000000..2fb96fc05e --- /dev/null +++ b/walletkit/walletkit-ui/contexts/StoreServiceProvider.tsx @@ -0,0 +1,114 @@ +import { + EnvironmentNetwork, + getDefaultDefiChainURL, +} from "@waveshq/walletkit-core"; +import React, { + createContext, + PropsWithChildren, + useContext, + useEffect, + useMemo, + useState, +} from "react"; + +import { BaseLogger } from "./logger"; +import { useNetworkContext } from "./NetworkContext"; + +interface ServiceProviderContextProps { + api: { + get: () => Promise; + set: (url: NonNullable) => Promise; + }; + logger: BaseLogger; +} + +interface ServiceProviderURLProps extends ServiceProviderContextProps { + network: EnvironmentNetwork; +} + +interface ServiceProviderLoader { + isUrlLoaded: boolean; + url: NonNullable; +} + +function useServiceProviderUrl({ + api, + network, + logger, +}: ServiceProviderURLProps): ServiceProviderLoader { + const [isUrlLoaded, setIsUrlLoaded] = useState(false); + const defaultDefichainURL = getDefaultDefiChainURL(network); + const [url, setUrl] = useState>(defaultDefichainURL); + + useEffect(() => { + api + .get() + .then((val) => { + setUrl(val !== undefined ? val : defaultDefichainURL); + }) + .catch((err) => logger.error(err)) + .finally(() => setIsUrlLoaded(true)); + }, [url, network]); + + return { + isUrlLoaded, + url, + }; +} + +interface ServiceProviderContextI { + url: NonNullable; + defaultUrl: string; + isCustomUrl: boolean; + setUrl: (val: NonNullable) => Promise; +} + +const ServiceProviderContext = createContext( + undefined as any, +); + +export function useServiceProviderContext(): ServiceProviderContextI { + return useContext(ServiceProviderContext); +} + +export function StoreServiceProvider( + props: ServiceProviderContextProps & PropsWithChildren, +): JSX.Element | null { + const { api, children, logger } = props; + const { network } = useNetworkContext(); + const { url } = useServiceProviderUrl({ + api, + network, + logger, + }); + const defaultUrl = getDefaultDefiChainURL(network); + const [currentUrl, setCurrentUrl] = useState(url); + + useEffect(() => { + setCurrentUrl(url); + }, [url]); + + const isCustomUrl = useMemo( + () => currentUrl !== defaultUrl, + [currentUrl, defaultUrl], + ); + + const setUrl = async (newUrl: string): Promise => { + setCurrentUrl(newUrl); + await api.set(newUrl); + }; + + // eslint-disable-next-line react/jsx-no-constructed-context-values + const context: ServiceProviderContextI = { + url: currentUrl === undefined ? defaultUrl : currentUrl, + isCustomUrl, + defaultUrl, + setUrl, + }; + + return ( + + {children} + + ); +} diff --git a/walletkit/walletkit-ui/contexts/ThemeProvider.test.tsx b/walletkit/walletkit-ui/contexts/ThemeProvider.test.tsx new file mode 100644 index 0000000000..af7825f2d5 --- /dev/null +++ b/walletkit/walletkit-ui/contexts/ThemeProvider.test.tsx @@ -0,0 +1,84 @@ +/** + * @jest-environment jsdom + */ + +import { render } from "@testing-library/react"; +import { renderHook } from "@testing-library/react-hooks"; +import React from "react"; + +import { ThemeProvider, useTheme, useThemeContext } from "./ThemeProvider"; + +const consoleLog = jest.spyOn(console, "log").mockImplementation(jest.fn); +const consoleError = jest.spyOn(console, "error").mockImplementation(jest.fn); +const logger = { error: () => consoleError, info: () => consoleLog }; + +describe("useTheme hook test", () => { + it("should pass when theme is not set", async () => { + const desiredTheme = "dark"; + const api = { + set: jest.fn(), + get: async () => null, + }; + const { result, waitForNextUpdate } = renderHook(() => + useTheme({ + api, + colorScheme: desiredTheme, + logger, + }), + ); + await waitForNextUpdate(); + expect(result.current.theme).toBe(desiredTheme); + expect(result.current.isThemeLoaded).toBe(true); + }); + + it("should pass when theme is already set", async () => { + const desiredTheme = "dark"; + const api = { + set: jest.fn(), + get: async () => desiredTheme, + }; + const { result, waitForNextUpdate } = renderHook(() => + useTheme({ api, colorScheme: "light", logger }), + ); + await waitForNextUpdate(); + expect(result.current.theme).toBe(desiredTheme); + expect(result.current.isThemeLoaded).toBe(true); + }); + + it("should pass when theme is not set and colorScheme is not defined", async () => { + const api = { + set: jest.fn(), + get: async () => null, + }; + const { result, waitForNextUpdate } = renderHook(() => + useTheme({ api, logger }), + ); + await waitForNextUpdate(); + expect(result.current.theme).toBe("light"); + expect(result.current.isThemeLoaded).toBe(true); + }); +}); + +describe("ThemeProvider Context test", () => { + it("should match snapshot", () => { + function ThemeProviderComponent(): JSX.Element { + const { isLight, theme } = useThemeContext(); + return ( +
+ {isLight.toString()} + {theme} +
+ ); + } + const api = { + set: jest.fn(), + get: async () => "light", + }; + const rendered = render( + + + , + ); + expect(rendered).toMatchSnapshot(); + }); +}); diff --git a/walletkit/walletkit-ui/contexts/ThemeProvider.tsx b/walletkit/walletkit-ui/contexts/ThemeProvider.tsx new file mode 100644 index 0000000000..e03fd85ea9 --- /dev/null +++ b/walletkit/walletkit-ui/contexts/ThemeProvider.tsx @@ -0,0 +1,95 @@ +import React, { + createContext, + PropsWithChildren, + useContext, + useEffect, + useState, +} from "react"; + +import { BaseLogger } from "./logger"; + +interface ThemeLoader { + theme: NonNullable; + isThemeLoaded: boolean; +} + +type ColorSchemeName = "light" | "dark" | null | undefined; + +interface ThemeContextI { + api: { + get: () => Promise; + set: (language: NonNullable) => Promise; + }; + logger: BaseLogger; + colorScheme?: ColorSchemeName; +} + +export function useTheme({ + api, + colorScheme, + logger, +}: ThemeContextI): ThemeLoader { + const [isThemeLoaded, setIsThemeLoaded] = useState(false); + const [theme, setTheme] = useState>("light"); + + useEffect(() => { + api + .get() + .then((t) => { + let currentTheme: NonNullable = "light"; + if (t !== null && t !== undefined) { + currentTheme = t as NonNullable; + } else if (colorScheme !== null && colorScheme !== undefined) { + currentTheme = colorScheme; + } + setTheme(currentTheme); + }) + .catch(logger?.error) + .finally(() => setIsThemeLoaded(true)); + }, []); + + return { + isThemeLoaded, + theme, + }; +} + +interface Theme { + theme: NonNullable; + setTheme: (theme: NonNullable) => void; + isLight: boolean; +} + +const ThemeContext = createContext(undefined as any); + +export function useThemeContext(): Theme { + return useContext(ThemeContext); +} + +export interface ThemeProviderProps extends PropsWithChildren<{}> { + logger: BaseLogger; +} + +export function ThemeProvider( + props: ThemeContextI & React.PropsWithChildren, +): JSX.Element | null { + const { children, api, colorScheme, logger } = props; + const { theme } = useTheme({ api, colorScheme, logger }); + const [currentTheme, setTheme] = + useState>(theme); + + useEffect(() => { + setTheme(theme); + }, [theme]); + + // eslint-disable-next-line react/jsx-no-constructed-context-values + const context: Theme = { + theme: currentTheme, + setTheme, + isLight: currentTheme === "light", + }; + + return ( + {children} + ); +} diff --git a/walletkit/walletkit-ui/contexts/WalletNodeProvider.tsx b/walletkit/walletkit-ui/contexts/WalletNodeProvider.tsx new file mode 100644 index 0000000000..35425a18f9 --- /dev/null +++ b/walletkit/walletkit-ui/contexts/WalletNodeProvider.tsx @@ -0,0 +1,151 @@ +import { + WalletHdNode, + WalletHdNodeProvider, +} from "@defichain/jellyfish-wallet"; +import { + EncryptedHdNodeProvider, + EncryptedProviderData, + PromptPassphrase, +} from "@defichain/jellyfish-wallet-encrypted"; +import { + MnemonicHdNodeProvider, + MnemonicProviderData, +} from "@defichain/jellyfish-wallet-mnemonic"; +import { EnvironmentNetwork } from "@waveshq/walletkit-core"; +import React, { + createContext, + PropsWithChildren, + useContext, + useMemo, +} from "react"; + +import { useNetworkContext } from "./NetworkContext"; +import { WalletPersistenceDataI, WalletType } from "./WalletPersistenceContext"; + +export interface PromptInterface { + prompt: PromptPassphrase; +} + +export interface EncryptedMnemonicWalletI { + initProvider: ( + data: WalletPersistenceDataI, + network: EnvironmentNetwork, + promptInterface: PromptInterface, + ) => EncryptedHdNodeProvider; + toData: ( + mnemonic: string[], + network: EnvironmentNetwork, + passphrase: string, + ) => Promise>; + generateWords?: () => string[]; +} + +export interface UnencryptedMnemonicWalletI { + initProvider: ( + data: WalletPersistenceDataI, + network: EnvironmentNetwork, + ) => MnemonicHdNodeProvider; + toData: ( + mnemonic: string[], + network: EnvironmentNetwork, + ) => WalletPersistenceDataI; + generateWords?: () => string[]; +} + +interface WalletNodeContextI { + provider: WalletHdNodeProvider; + /** + * Raw WalletPersistenceDataI that is included in WalletHdNodeProvider + * No risk of including it in context as it's part of the provider. + */ + data: WalletPersistenceDataI; +} + +const WalletNodeContext = createContext(undefined as any); + +function MnemonicUnprotectedProvider( + props: WalletNodeProviderProps, +): JSX.Element | null { + const { MnemonicUnprotected, children, data } = props; + const { network } = useNetworkContext(); + + const provider = useMemo( + () => MnemonicUnprotected.initProvider(data, network), + [network, data], + ); + + return ( + // eslint-disable-next-line react/jsx-no-constructed-context-values + + {children} + + ); +} + +function MnemonicEncryptedProvider( + props: WalletNodeProviderProps, +): JSX.Element | null { + const { MnemonicEncrypted, children, data } = props; + const { network } = useNetworkContext(); + + const provider = useMemo( + () => + MnemonicEncrypted.initProvider(data, network, { + /** + * wallet context only use for READ purpose (non signing) + * see {@link TransactionAuthorization} for signing implementation + */ + async prompt() { + throw new Error("No UI attached for passphrase prompting"); + }, + }), + [network, data], + ); + + return ( + // eslint-disable-next-line react/jsx-no-constructed-context-values + + {children} + + ); +} + +export function useWalletNodeContext(): WalletNodeContextI { + return useContext(WalletNodeContext); +} + +interface WalletNodeProviderProps extends PropsWithChildren { + data: WalletPersistenceDataI; + + // eslint-disable-next-line react/no-unused-prop-types + MnemonicEncrypted: EncryptedMnemonicWalletI; + + // eslint-disable-next-line react/no-unused-prop-types + MnemonicUnprotected: UnencryptedMnemonicWalletI; +} + +/** + * Automatically determine the correct WalletProvider to use based on the wallet type. + */ +export function WalletNodeProvider( + props: WalletNodeProviderProps, +): JSX.Element | null { + const { data, children } = props; + if (data.type === WalletType.MNEMONIC_UNPROTECTED) { + return ( + + {children} + + ); + } + + if (data.type === WalletType.MNEMONIC_ENCRYPTED) { + return ( + + {children} + + ); + } + + throw new Error(`wallet type: ${data.type as string} not available`); +} diff --git a/walletkit/walletkit-ui/contexts/WalletPersistenceContext.tsx b/walletkit/walletkit-ui/contexts/WalletPersistenceContext.tsx new file mode 100644 index 0000000000..0eaa337e5a --- /dev/null +++ b/walletkit/walletkit-ui/contexts/WalletPersistenceContext.tsx @@ -0,0 +1,101 @@ +import React, { + createContext, + PropsWithChildren, + useContext, + useEffect, + useState, +} from "react"; + +import { BaseLogger } from "./logger"; +import { useNetworkContext } from "./NetworkContext"; + +export enum WalletType { + MNEMONIC_UNPROTECTED = "MNEMONIC_UNPROTECTED", + MNEMONIC_ENCRYPTED = "MNEMONIC_ENCRYPTED", +} + +export interface WalletPersistenceDataI { + type: WalletType; + /* To migrate between app version upgrade */ + version: "v1"; + /* Raw Data encoded in WalletType specified format */ + raw: T; +} + +interface WalletPersistenceContextI { + isLoaded: boolean; + wallets: Array>; + /** + * @param {WalletPersistenceDataI} data to set, only 1 wallet is supported for now + */ + setWallet: (data: WalletPersistenceDataI) => Promise; + clearWallets: () => Promise; +} + +const WalletPersistenceContext = createContext( + undefined as any, +); + +/** + * WalletManagement Context wrapped within + * + * This context enable wallet management by allow access to all configured wallets. + * Setting, removing and getting individual wallet. + */ +export function useWalletPersistenceContext(): WalletPersistenceContextI { + return useContext(WalletPersistenceContext); +} + +interface WalletPersistenceProviderI { + api: { + get: () => Promise>>; + set: (wallets: Array>) => Promise; + setLength: (count: number) => Promise; + setActive: (count: number) => Promise; + }; + logger: BaseLogger; +} + +export function WalletPersistenceProvider( + props: WalletPersistenceProviderI & PropsWithChildren, +): JSX.Element | null { + const { api, logger, children } = props; + const { network } = useNetworkContext(); + const [isLoaded, setIsLoaded] = useState(false); + const [dataList, setDataList] = useState>>( + [], + ); + + useEffect(() => { + api + .get() + .then((d: Array>) => { + setDataList(d); + }) + .catch(logger.error) + .finally(() => setIsLoaded(true)); + }, [network]); // api is network dependent + + // eslint-disable-next-line react/jsx-no-constructed-context-values + const management: WalletPersistenceContextI = { + isLoaded, + wallets: dataList, + async setWallet(data: WalletPersistenceDataI): Promise { + await api.set([data]); + setDataList(await api.get()); + }, + async clearWallets(): Promise { + // remove address length and active address + await api.setLength(0); + await api.setActive(0); + await api.set([]); + setDataList(await api.get()); + }, + }; + + return ( + + {children} + + ); +} diff --git a/walletkit/walletkit-ui/contexts/WhaleContext.test.tsx b/walletkit/walletkit-ui/contexts/WhaleContext.test.tsx new file mode 100644 index 0000000000..5277bf74b2 --- /dev/null +++ b/walletkit/walletkit-ui/contexts/WhaleContext.test.tsx @@ -0,0 +1,205 @@ +/** + * @jest-environment jsdom + */ + +import { render } from "@testing-library/react"; +import { EnvironmentNetwork } from "@waveshq/walletkit-core"; +import React from "react"; + +import * as NetworkContext from "./NetworkContext"; +import * as ServiceProviderContext from "./StoreServiceProvider"; +import { useWhaleApiClient, WhaleProvider } from "./WhaleContext"; + +const networkContext = jest.spyOn(NetworkContext, "useNetworkContext"); +const serviceProviderContext = jest.spyOn( + ServiceProviderContext, + "useServiceProviderContext", +); + +describe("Whale Context test", () => { + const networkDetails = [ + { + url: "https://ocean.defichain.com", + network: "mainnet", + name: EnvironmentNetwork.MainNet, + }, + { + url: "https://testnet.ocean.jellyfishsdk.com", + network: "testnet", + name: EnvironmentNetwork.TestNet, + }, + { + url: "https://playground.jellyfishsdk.com", + network: "regtest", + name: EnvironmentNetwork.RemotePlayground, + }, + { + url: "http://localhost:19553", + network: "regtest", + name: EnvironmentNetwork.LocalPlayground, + }, + { + url: "http://devnet.ocean.jellyfishsdk.com", + network: "devnet", + name: EnvironmentNetwork.DevNet, + }, + { + url: "https://changi.ocean.jellyfishsdk.com", + network: "changi", + name: EnvironmentNetwork.Changi, + }, + ]; + + networkDetails.forEach((networkDetail) => { + describe(`Whale Context test for ${networkDetail.name}`, () => { + it("should match snapshot", () => { + networkContext.mockImplementation( + () => + ({ + network: networkDetail.name, + }) as any, + ); + serviceProviderContext.mockImplementation( + () => + ({ + url: networkDetail.url, + }) as any, + ); + function WhaleProviderComponent(): JSX.Element { + const client = useWhaleApiClient() as any; + expect(Object.keys(client)).toEqual( + expect.arrayContaining([ + "options", + "rpc", + "address", + "poolpairs", + "transactions", + "tokens", + "masternodes", + "blocks", + "oracles", + "prices", + "stats", + "rawtx", + "fee", + "loan", + ]), + ); + const options = { + version: "v0", + timeout: 60000, + url: networkDetail.url, + network: networkDetail.network, + }; + expect(client.options).toMatchObject(options); + return ( +
+ {JSON.stringify(client.options)} +
+ ); + } + + const rendered = render( + + + , + ); + expect(rendered).toMatchSnapshot(); + }); + }); + }); +}); + +describe("Whale custom provider url test", () => { + const networkDetails = [ + { + url: "https://custom.mainnet.com", + network: "mainnet", + name: EnvironmentNetwork.MainNet, + }, + { + url: "https://custom.testnet.com", + network: "testnet", + name: EnvironmentNetwork.TestNet, + }, + { + url: "https://custom.playground.com", + network: "regtest", + name: EnvironmentNetwork.RemotePlayground, + }, + { + url: "https://custom.local.com", + network: "regtest", + name: EnvironmentNetwork.LocalPlayground, + }, + { + url: "https://custom.devnet.com", + network: "devnet", + name: EnvironmentNetwork.DevNet, + }, + { + url: "https://custom.changi.com", + network: "changi", + name: EnvironmentNetwork.Changi, + }, + ]; + + networkDetails.forEach((networkDetail) => { + describe(`Whale custom provider url test for ${networkDetail.name}`, () => { + it(`should match custom provider url: ${networkDetail.url}`, () => { + networkContext.mockImplementation( + () => + ({ + network: networkDetail.name, + }) as any, + ); + serviceProviderContext.mockImplementation( + () => + ({ + url: networkDetail.url, + }) as any, + ); + function WhaleProviderComponent(): JSX.Element { + const client = useWhaleApiClient() as any; + expect(Object.keys(client)).toEqual( + expect.arrayContaining([ + "options", + "rpc", + "address", + "poolpairs", + "transactions", + "tokens", + "masternodes", + "blocks", + "oracles", + "prices", + "stats", + "rawtx", + "fee", + "loan", + ]), + ); + const options = { + version: "v0", + timeout: 60000, + url: networkDetail.url, + network: networkDetail.network, + }; + expect(client.options).toMatchObject(options); + return ( +
+ {JSON.stringify(client.options)} +
+ ); + } + + const rendered = render( + + + , + ); + expect(rendered).toMatchSnapshot(); + }); + }); + }); +}); diff --git a/walletkit/walletkit-ui/contexts/WhaleContext.tsx b/walletkit/walletkit-ui/contexts/WhaleContext.tsx new file mode 100644 index 0000000000..c3f1ab7a07 --- /dev/null +++ b/walletkit/walletkit-ui/contexts/WhaleContext.tsx @@ -0,0 +1,46 @@ +import { WhaleApiClient, WhaleRpcClient } from "@defichain/whale-api-client"; +import { + newOceanOptions, + newWhaleAPIClient, + newWhaleRpcClient, +} from "@waveshq/walletkit-core"; +import React, { createContext, useContext, useMemo } from "react"; + +import { useNetworkContext } from "./NetworkContext"; +import { useServiceProviderContext } from "./StoreServiceProvider"; + +const WhaleApiClientContext = createContext<{ + whaleAPI: WhaleApiClient; + whaleRPC: WhaleRpcClient; +}>(undefined as any); + +export function useWhaleApiClient(): WhaleApiClient { + return useContext(WhaleApiClientContext).whaleAPI; +} + +export function useWhaleRpcClient(): WhaleRpcClient { + return useContext(WhaleApiClientContext).whaleRPC; +} + +export function WhaleProvider({ + children, +}: React.PropsWithChildren): JSX.Element | null { + const { network } = useNetworkContext(); + + // Do not destructure, some projects are not wrapped with ServiceProvider + const service = useServiceProviderContext(); + + const client = useMemo( + () => ({ + whaleAPI: newWhaleAPIClient(newOceanOptions(network, service?.url)), + whaleRPC: newWhaleRpcClient(newOceanOptions(network, service?.url)), + }), + [network, service?.url], + ); + + return ( + + {children} + + ); +} diff --git a/walletkit/walletkit-ui/contexts/__snapshots__/LanguageProvider.test.tsx.snap b/walletkit/walletkit-ui/contexts/__snapshots__/LanguageProvider.test.tsx.snap new file mode 100644 index 0000000000..66c47fdc98 --- /dev/null +++ b/walletkit/walletkit-ui/contexts/__snapshots__/LanguageProvider.test.tsx.snap @@ -0,0 +1,74 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`LanguageProvider Context test should match snapshot 1`] = ` +{ + "asFragment": [Function], + "baseElement": +
+
+ + en + +
+
+ , + "container":
+
+ + en + +
+
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; diff --git a/walletkit/walletkit-ui/contexts/__snapshots__/ThemeProvider.test.tsx.snap b/walletkit/walletkit-ui/contexts/__snapshots__/ThemeProvider.test.tsx.snap new file mode 100644 index 0000000000..534a97abe7 --- /dev/null +++ b/walletkit/walletkit-ui/contexts/__snapshots__/ThemeProvider.test.tsx.snap @@ -0,0 +1,80 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ThemeProvider Context test should match snapshot 1`] = ` +{ + "asFragment": [Function], + "baseElement": +
+
+ + true + + + light + +
+
+ , + "container":
+
+ + true + + + light + +
+
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; diff --git a/walletkit/walletkit-ui/contexts/__snapshots__/WhaleContext.test.tsx.snap b/walletkit/walletkit-ui/contexts/__snapshots__/WhaleContext.test.tsx.snap new file mode 100644 index 0000000000..a3cd9a7932 --- /dev/null +++ b/walletkit/walletkit-ui/contexts/__snapshots__/WhaleContext.test.tsx.snap @@ -0,0 +1,877 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Whale Context test Whale Context test for Changi should match snapshot 1`] = ` +{ + "asFragment": [Function], + "baseElement": +
+
+ + {"url":"https://changi.ocean.jellyfishsdk.com","timeout":60000,"version":"v0","network":"changi"} + +
+
+ , + "container":
+
+ + {"url":"https://changi.ocean.jellyfishsdk.com","timeout":60000,"version":"v0","network":"changi"} + +
+
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; + +exports[`Whale Context test Whale Context test for DevNet should match snapshot 1`] = ` +{ + "asFragment": [Function], + "baseElement": +
+
+ + {"url":"http://devnet.ocean.jellyfishsdk.com","timeout":60000,"version":"v0","network":"devnet"} + +
+
+ , + "container":
+
+ + {"url":"http://devnet.ocean.jellyfishsdk.com","timeout":60000,"version":"v0","network":"devnet"} + +
+
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; + +exports[`Whale Context test Whale Context test for Local should match snapshot 1`] = ` +{ + "asFragment": [Function], + "baseElement": +
+
+ + {"url":"http://localhost:19553","timeout":60000,"version":"v0","network":"regtest"} + +
+
+ , + "container":
+
+ + {"url":"http://localhost:19553","timeout":60000,"version":"v0","network":"regtest"} + +
+
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; + +exports[`Whale Context test Whale Context test for MainNet should match snapshot 1`] = ` +{ + "asFragment": [Function], + "baseElement": +
+
+ + {"url":"https://ocean.defichain.com","timeout":60000,"version":"v0","network":"mainnet"} + +
+
+ , + "container":
+
+ + {"url":"https://ocean.defichain.com","timeout":60000,"version":"v0","network":"mainnet"} + +
+
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; + +exports[`Whale Context test Whale Context test for Playground should match snapshot 1`] = ` +{ + "asFragment": [Function], + "baseElement": +
+
+ + {"url":"https://playground.jellyfishsdk.com","timeout":60000,"version":"v0","network":"regtest"} + +
+
+ , + "container":
+
+ + {"url":"https://playground.jellyfishsdk.com","timeout":60000,"version":"v0","network":"regtest"} + +
+
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; + +exports[`Whale Context test Whale Context test for TestNet should match snapshot 1`] = ` +{ + "asFragment": [Function], + "baseElement": +
+
+ + {"url":"https://testnet.ocean.jellyfishsdk.com","timeout":60000,"version":"v0","network":"testnet"} + +
+
+ , + "container":
+
+ + {"url":"https://testnet.ocean.jellyfishsdk.com","timeout":60000,"version":"v0","network":"testnet"} + +
+
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; + +exports[`Whale custom provider url test Whale custom provider url test for Changi should match custom provider url: https://custom.changi.com 1`] = ` +{ + "asFragment": [Function], + "baseElement": +
+
+ + {"url":"https://custom.changi.com","timeout":60000,"version":"v0","network":"changi"} + +
+
+ , + "container":
+
+ + {"url":"https://custom.changi.com","timeout":60000,"version":"v0","network":"changi"} + +
+
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; + +exports[`Whale custom provider url test Whale custom provider url test for DevNet should match custom provider url: https://custom.devnet.com 1`] = ` +{ + "asFragment": [Function], + "baseElement": +
+
+ + {"url":"https://custom.devnet.com","timeout":60000,"version":"v0","network":"devnet"} + +
+
+ , + "container":
+
+ + {"url":"https://custom.devnet.com","timeout":60000,"version":"v0","network":"devnet"} + +
+
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; + +exports[`Whale custom provider url test Whale custom provider url test for Local should match custom provider url: https://custom.local.com 1`] = ` +{ + "asFragment": [Function], + "baseElement": +
+
+ + {"url":"https://custom.local.com","timeout":60000,"version":"v0","network":"regtest"} + +
+
+ , + "container":
+
+ + {"url":"https://custom.local.com","timeout":60000,"version":"v0","network":"regtest"} + +
+
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; + +exports[`Whale custom provider url test Whale custom provider url test for MainNet should match custom provider url: https://custom.mainnet.com 1`] = ` +{ + "asFragment": [Function], + "baseElement": +
+
+ + {"url":"https://custom.mainnet.com","timeout":60000,"version":"v0","network":"mainnet"} + +
+
+ , + "container":
+
+ + {"url":"https://custom.mainnet.com","timeout":60000,"version":"v0","network":"mainnet"} + +
+
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; + +exports[`Whale custom provider url test Whale custom provider url test for Playground should match custom provider url: https://custom.playground.com 1`] = ` +{ + "asFragment": [Function], + "baseElement": +
+
+ + {"url":"https://custom.playground.com","timeout":60000,"version":"v0","network":"regtest"} + +
+
+ , + "container":
+
+ + {"url":"https://custom.playground.com","timeout":60000,"version":"v0","network":"regtest"} + +
+
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; + +exports[`Whale custom provider url test Whale custom provider url test for TestNet should match custom provider url: https://custom.testnet.com 1`] = ` +{ + "asFragment": [Function], + "baseElement": +
+
+ + {"url":"https://custom.testnet.com","timeout":60000,"version":"v0","network":"testnet"} + +
+
+ , + "container":
+
+ + {"url":"https://custom.testnet.com","timeout":60000,"version":"v0","network":"testnet"} + +
+
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; diff --git a/walletkit/walletkit-ui/contexts/index.ts b/walletkit/walletkit-ui/contexts/index.ts new file mode 100644 index 0000000000..ccf79e774a --- /dev/null +++ b/walletkit/walletkit-ui/contexts/index.ts @@ -0,0 +1,12 @@ +export * from "./DeFiScanContext"; +export * from "./DisplayBalanceContext"; +export * from "./LanguageProvider"; +export * from "./NetworkContext"; +export * from "./PlaygroundContext"; +export * from "./StatsProvider"; +export * from "./StoreProvider"; +export * from "./StoreServiceProvider"; +export * from "./ThemeProvider"; +export * from "./WalletNodeProvider"; +export * from "./WalletPersistenceContext"; +export * from "./WhaleContext"; diff --git a/walletkit/walletkit-ui/contexts/logger.ts b/walletkit/walletkit-ui/contexts/logger.ts new file mode 100644 index 0000000000..5d77cbc6e0 --- /dev/null +++ b/walletkit/walletkit-ui/contexts/logger.ts @@ -0,0 +1,4 @@ +export interface BaseLogger { + error: (error: any) => void; + info: (message: string) => void; +} diff --git a/walletkit/walletkit-ui/data/exchanges.ts b/walletkit/walletkit-ui/data/exchanges.ts new file mode 100644 index 0000000000..3ceb89d28a --- /dev/null +++ b/walletkit/walletkit-ui/data/exchanges.ts @@ -0,0 +1,59 @@ +export interface ExchangeProps { + name: string; + url: string; +} + +export const exchanges: ExchangeProps[] = [ + { + name: "Kucoin", + url: "https://www.kucoin.com/trade/DFI-BTC", + }, + { + name: "Huobi", + url: "https://www.huobi.com/en-us/exchange/dfi_usdt", + }, + { + name: "Gate.io", + url: "https://www.gate.io/trade/DFI_USDT", + }, + { + name: "Bittrex", + url: "https://global.bittrex.com/Market/Index?MarketName=BTC-DFI", + }, + { + name: "Bitrue", + url: "https://www.bitrue.com/trade/dfi_btc", + }, + { + name: "Latoken", + url: "https://latoken.com/exchange/DFI_BTC", + }, + { + name: "DFX", + url: "https://dfx.swiss/en/", + }, + { + name: "Transak", + url: "https://global.transak.com/", + }, + { + name: "EasyCrypto (Australia)", + url: "https://easycrypto.com/au/buy-sell/dfi-defichain", + }, + { + name: "EasyCrypto (New Zealand)", + url: "https://easycrypto.com/nz/buy-sell/dfi-defichain", + }, + { + name: "Bybit", + url: "https://www.bybit.com/en-US/trade/spot/DFI/USDT", + }, + { + name: "Swyftx", + url: "https://swyftx.com/au/buy/defichain/", + }, + { + name: "Cake DeFi", + url: "https://cakedefi.com/", + }, +]; diff --git a/walletkit/walletkit-ui/data/index.ts b/walletkit/walletkit-ui/data/index.ts new file mode 100644 index 0000000000..0c5f39eff9 --- /dev/null +++ b/walletkit/walletkit-ui/data/index.ts @@ -0,0 +1 @@ +export * from "./exchanges"; diff --git a/walletkit/walletkit-ui/hooks/index.ts b/walletkit/walletkit-ui/hooks/index.ts new file mode 100644 index 0000000000..21f6f430ac --- /dev/null +++ b/walletkit/walletkit-ui/hooks/index.ts @@ -0,0 +1,2 @@ +export * from "./useCollateralizationRatio"; +export * from "./useVaultStatus"; diff --git a/walletkit/walletkit-ui/hooks/useCollateralizationRatio.tsx b/walletkit/walletkit-ui/hooks/useCollateralizationRatio.tsx new file mode 100644 index 0000000000..e51c560034 --- /dev/null +++ b/walletkit/walletkit-ui/hooks/useCollateralizationRatio.tsx @@ -0,0 +1,197 @@ +/* eslint-disable @typescript-eslint/no-shadow */ +import BigNumber from "bignumber.js"; + +import { + CollateralizationRatioProps, + CollateralizationRatioStats, + VaultStatus, +} from "../store/types/VaultStatus"; + +export function useCollateralRatioStats({ + colRatio, + minColRatio, + totalLoanAmount, + totalCollateralValue, +}: CollateralizationRatioProps): CollateralizationRatioStats { + const atRiskThreshold = new BigNumber(minColRatio).multipliedBy(1.5); + const liquidatedThreshold = new BigNumber(minColRatio).multipliedBy(1.25); + const isInLiquidation = + totalLoanAmount.gt(0) && colRatio.isLessThan(liquidatedThreshold); + const isAtRisk = + totalLoanAmount.gt(0) && colRatio.isLessThan(atRiskThreshold); + return { + atRiskThreshold, + liquidatedThreshold, + isInLiquidation, + isAtRisk, + isHealthy: !isInLiquidation && !isAtRisk && totalLoanAmount.gt(0), + isReady: + !isInLiquidation && + !isAtRisk && + totalLoanAmount.eq(0) && + totalCollateralValue !== undefined && + totalCollateralValue.gt(0), + }; +} + +// export function useCollateralizationRatioColor( +// props: CollateralizationRatioProps +// ): ThemedProps { +// const style: ThemedProps = {}; +// const stats = useCollateralRatioStats(props); + +// if (stats.isInLiquidation) { +// style.light = tailwind("text-error-500"); +// style.dark = tailwind("text-darkerror-500"); +// } else if (stats.isAtRisk) { +// style.light = tailwind("text-warning-500"); +// style.dark = tailwind("text-darkwarning-500"); +// } else if (stats.isHealthy) { +// style.light = tailwind("text-success-500"); +// style.dark = tailwind("text-darksuccess-500"); +// } +// return style; +// } + +// export function getVaultStatusColor( +// status: string, +// isLight: boolean, +// isText: boolean = false +// ): string { +// if (status === VaultStatus.NearLiquidation) { +// return isText ? "text-red-v2" : getColor("red-v2"); +// } else if (status === VaultStatus.AtRisk) { +// return isText ? "text-orange-v2" : getColor("orange-v2"); +// } else if (status === VaultStatus.Healthy || status === VaultStatus.Ready) { +// return isText ? "text-green-v2" : getColor("green-v2"); +// } +// return isText +// ? isLight +// ? "text-mono-light-v2-500" +// : "text-mono-dark-v2-500" +// : getColor(isLight ? "mono-light-v2-300" : "mono-dark-v2-300"); +// } + +export function getVaultStatusText(status: string): string { + switch (status) { + case VaultStatus.Ready: + return "Ready"; + case VaultStatus.Halted: + return "Halted"; + default: + return "Empty"; + } +} + +export function useResultingCollateralizationRatioByCollateral({ + collateralValue, + collateralRatio, + minCollateralRatio, + totalLoanAmount, + numOfColorBars = 6, + totalCollateralValueInUSD, +}: { + collateralValue: string; + collateralRatio: BigNumber; + minCollateralRatio: BigNumber; + totalLoanAmount: BigNumber; + totalCollateralValue?: BigNumber; + numOfColorBars?: number; + totalCollateralValueInUSD: BigNumber; +}): { + resultingColRatio: BigNumber; + displayedColorBars: number; +} { + const hasCollateralRatio = + !new BigNumber(collateralRatio).isNaN() && + new BigNumber(collateralRatio).isPositive(); + const resultingColRatio = + collateralValue === "" || + !hasCollateralRatio || + new BigNumber(collateralValue).isZero() + ? new BigNumber(collateralRatio) + : totalCollateralValueInUSD.dividedBy(totalLoanAmount).multipliedBy(100); + + const numOfColorBarPerStatus = numOfColorBars / 3; // (3): liquidation, at risk, healthy + const healthyThresholdRatio = 1.75; + const atRiskThresholdRatio = 1.5; + const liquidatedThresholdRatio = 1.25; + const atRiskThreshold = new BigNumber(minCollateralRatio).multipliedBy( + atRiskThresholdRatio, + ); + const liquidatedThreshold = new BigNumber(minCollateralRatio).multipliedBy( + liquidatedThresholdRatio, + ); + + const isAtRisk = + totalLoanAmount.gt(0) && resultingColRatio.isLessThan(atRiskThreshold); + const isInLiquidation = + totalLoanAmount.gt(0) && resultingColRatio.isLessThan(liquidatedThreshold); + const isHealthy = !isInLiquidation && !isAtRisk && totalLoanAmount.gt(0); + + const getRatio = (): number => { + if (isHealthy) { + return healthyThresholdRatio; + } + if (isAtRisk && !isInLiquidation) { + return atRiskThresholdRatio; + } + return liquidatedThresholdRatio; + }; + + const getColorBarsCount = ( + numOfColorBarPerStatus: number, + minCollateralRatio: BigNumber, + resultingCollateralRatio: BigNumber, + thresholdRatio: number, + isHealthy: boolean, + ): number => { + let colorBarsCount = -1; + let index = 1; + while (colorBarsCount === -1 && index <= numOfColorBarPerStatus) { + const colorBarMaxAmount = minCollateralRatio.plus( + minCollateralRatio.multipliedBy( + new BigNumber(thresholdRatio) + .minus(1) + .dividedBy(isHealthy ? 1 : numOfColorBarPerStatus) + .times(index), // divide threshold to number of bars + ), + ); + + if (resultingCollateralRatio.isLessThanOrEqualTo(colorBarMaxAmount)) { + colorBarsCount = index; + } + + index += 1; + } + + return colorBarsCount; + }; + + const colorBarsCount = getColorBarsCount( + numOfColorBarPerStatus, + minCollateralRatio, + resultingColRatio, + getRatio(), + isHealthy, + ); + + let displayedColorBars = -1; + + if (resultingColRatio.isLessThanOrEqualTo(0)) { + displayedColorBars = -1; + } else if (isHealthy && colorBarsCount > 0) { + displayedColorBars = colorBarsCount + numOfColorBarPerStatus * 2; + } else if (isHealthy && colorBarsCount === -1) { + displayedColorBars = numOfColorBars; // display full color bar + } else if (isAtRisk && !isInLiquidation) { + displayedColorBars = colorBarsCount + numOfColorBarPerStatus; + } else { + displayedColorBars = colorBarsCount; + } + + return { + displayedColorBars, + resultingColRatio, + }; +} diff --git a/walletkit/walletkit-ui/hooks/useVaultStatus.tsx b/walletkit/walletkit-ui/hooks/useVaultStatus.tsx new file mode 100644 index 0000000000..1ba34e4959 --- /dev/null +++ b/walletkit/walletkit-ui/hooks/useVaultStatus.tsx @@ -0,0 +1,43 @@ +import { LoanVaultState } from "@defichain/whale-api-client/dist/api/loan"; +import BigNumber from "bignumber.js"; + +import { VaultHealthItem, VaultStatus } from "../store/types/VaultStatus"; +import { useCollateralRatioStats } from "./useCollateralizationRatio"; + +export function useVaultStatus( + status: LoanVaultState | undefined, + collateralRatio: BigNumber, + minColRatio: BigNumber, + totalLoanAmount: BigNumber, + totalCollateralValue: BigNumber, +): VaultHealthItem { + const colRatio = collateralRatio.gte(0) ? collateralRatio : new BigNumber(0); + const stats = useCollateralRatioStats({ + colRatio, + minColRatio, + totalLoanAmount, + totalCollateralValue, + }); + let vaultStatus: VaultStatus; + if (status === LoanVaultState.FROZEN) { + vaultStatus = VaultStatus.Halted; + } else if (status === LoanVaultState.UNKNOWN) { + vaultStatus = VaultStatus.Unknown; + } else if (status === LoanVaultState.IN_LIQUIDATION) { + vaultStatus = VaultStatus.Liquidated; + } else if (stats.isInLiquidation) { + vaultStatus = VaultStatus.NearLiquidation; + } else if (stats.isAtRisk) { + vaultStatus = VaultStatus.AtRisk; + } else if (stats.isHealthy) { + vaultStatus = VaultStatus.Healthy; + } else if (stats.isReady) { + vaultStatus = VaultStatus.Ready; + } else { + vaultStatus = VaultStatus.Empty; + } + return { + status: vaultStatus, + vaultStats: stats, + }; +} diff --git a/walletkit/walletkit-ui/images.d.ts b/walletkit/walletkit-ui/images.d.ts new file mode 100644 index 0000000000..f772359642 --- /dev/null +++ b/walletkit/walletkit-ui/images.d.ts @@ -0,0 +1,4 @@ +declare module "*.png" { + const src: string; + export default src; +} diff --git a/walletkit/walletkit-ui/index.ts b/walletkit/walletkit-ui/index.ts new file mode 100644 index 0000000000..f27bee26b1 --- /dev/null +++ b/walletkit/walletkit-ui/index.ts @@ -0,0 +1,4 @@ +export * from "./contexts"; +export * from "./data"; +export * from "./hooks"; +export * from "./store"; diff --git a/walletkit/walletkit-ui/store/auctions.ts b/walletkit/walletkit-ui/store/auctions.ts new file mode 100644 index 0000000000..ab4ff2318d --- /dev/null +++ b/walletkit/walletkit-ui/store/auctions.ts @@ -0,0 +1,108 @@ +import { WhaleApiClient } from "@defichain/whale-api-client"; +import { + LoanVaultLiquidated, + LoanVaultLiquidationBatch, + VaultAuctionBatchHistory, +} from "@defichain/whale-api-client/dist/api/loan"; +import { + createAsyncThunk, + createSelector, + createSlice, + PayloadAction, +} from "@reduxjs/toolkit"; + +export interface AuctionsState { + auctions: LoanVaultLiquidated[]; + hasFetchAuctionsData: boolean; + bidHistory: VaultAuctionBatchHistory[]; +} + +export interface AuctionBatchProps extends LoanVaultLiquidationBatch { + auction: LoanVaultLiquidated; + collateralTokenSymbols: string[]; +} + +const initialState: AuctionsState = { + auctions: [], + hasFetchAuctionsData: false, + bidHistory: [], +}; + +export const fetchAuctions = createAsyncThunk( + "wallet/fetchAuctions", + async ({ size = 200, client }: { size?: number; client: WhaleApiClient }) => + client.loan.listAuction(size), +); + +export const fetchBidHistory = createAsyncThunk( + "wallet/fetchBidHistory", + async ({ + vaultId, + liquidationHeight, + batchIndex, + client, + size = 200, + }: { + vaultId: string; + liquidationHeight: number; + batchIndex: number; + client: WhaleApiClient; + size: number; + }) => + client.loan.listVaultAuctionHistory( + vaultId, + liquidationHeight, + batchIndex, + size, + ), +); + +export const auctions = createSlice({ + name: "auctions", + initialState, + reducers: { + resetBidHistory: (state) => { + state.bidHistory = []; + }, + }, + extraReducers: (builder) => { + builder.addCase( + fetchAuctions.fulfilled, + (state, action: PayloadAction) => { + state.auctions = action.payload; + state.hasFetchAuctionsData = true; + }, + ); + builder.addCase( + fetchBidHistory.fulfilled, + (state, action: PayloadAction) => { + state.bidHistory = action.payload; + }, + ); + }, +}); + +/** + * Flattens the auctions -> batch + * Sorts by liquidation height + */ +export const getAuctionBatches = createSelector( + [(state: AuctionsState) => state.auctions], + (auctionsState) => + auctionsState.reduce( + (auctionBatches, auction): AuctionBatchProps[] => { + const filteredAuctionBatches = auctionBatches; + auction.batches.forEach((batch) => { + filteredAuctionBatches.push({ + ...batch, + auction, + collateralTokenSymbols: batch.collaterals.map( + ({ displaySymbol }) => displaySymbol, + ), + }); + }); + return filteredAuctionBatches; + }, + [], + ), +); diff --git a/walletkit/walletkit-ui/store/auctions.unit.ts b/walletkit/walletkit-ui/store/auctions.unit.ts new file mode 100644 index 0000000000..cfb224044e --- /dev/null +++ b/walletkit/walletkit-ui/store/auctions.unit.ts @@ -0,0 +1,253 @@ +import { + LoanVaultLiquidated, + LoanVaultLiquidationBatch, + LoanVaultState, + VaultAuctionBatchHistory, +} from "@defichain/whale-api-client/dist/api/loan"; + +import { + auctions, + AuctionsState, + fetchAuctions, + fetchBidHistory, + getAuctionBatches, +} from "./auctions"; + +describe("auctions reducer", () => { + let initialState: AuctionsState; + const loanBatchFoo: LoanVaultLiquidationBatch = { + index: 1, + collaterals: [ + { + id: "0", + amount: "0.16199027", + symbol: "DFI", + symbolKey: "DFI", + name: "Default Defi token", + displaySymbol: "DFI", + activePrice: { + id: "DFI-USD-1776", + key: "DFI-USD", + isLive: true, + block: { + hash: "478bf1d2322aaa010bb1b4575491a6b3594ec294cd9cb2e406a82e56c3315062", + height: 1776, + medianTime: 1641219432, + time: 1641219438, + }, + active: { + amount: "100.00000000", + weightage: 3, + oracles: { + active: 3, + total: 3, + }, + }, + next: { + amount: "100.00000000", + weightage: 3, + oracles: { + active: 3, + total: 3, + }, + }, + sort: "000006f0", + }, + }, + ], + loan: { + id: "14", + amount: "1.00043890", + symbol: "TU10", + symbolKey: "TU10", + name: "Decentralized TU10", + displaySymbol: "dTU10", + activePrice: { + id: "TU10-USD-1776", + key: "TU10-USD", + isLive: true, + block: { + hash: "478bf1d2322aaa010bb1b4575491a6b3594ec294cd9cb2e406a82e56c3315062", + height: 1776, + medianTime: 1641219432, + time: 1641219438, + }, + active: { + amount: "10.85668461", + weightage: 3, + oracles: { + active: 3, + total: 3, + }, + }, + next: { + amount: "10.85994194", + weightage: 3, + oracles: { + active: 3, + total: 3, + }, + }, + sort: "000006f0", + }, + }, + froms: [], + }; + const loanBatchBar: LoanVaultLiquidationBatch = { + index: 0, + collaterals: [ + { + id: "0", + amount: "0.83800973", + symbol: "DFI", + symbolKey: "DFI", + name: "Default Defi token", + displaySymbol: "DFI", + activePrice: { + id: "DFI-USD-1776", + key: "DFI-USD", + isLive: true, + block: { + hash: "478bf1d2322aaa010bb1b4575491a6b3594ec294cd9cb2e406a82e56c3315062", + height: 1776, + medianTime: 1641219432, + time: 1641219438, + }, + active: { + amount: "100.00000000", + weightage: 3, + oracles: { + active: 3, + total: 3, + }, + }, + next: { + amount: "100.00000000", + weightage: 3, + oracles: { + active: 3, + total: 3, + }, + }, + sort: "000006f0", + }, + }, + ], + loan: { + id: "11", + amount: "56.13801760", + symbol: "DUSD", + symbolKey: "DUSD", + name: "Decentralized USD", + displaySymbol: "DUSD", + }, + froms: [], + }; + const liquidatedVaults: LoanVaultLiquidated[] = [ + { + vaultId: + "0336a6e1bfeef859815f3e6c63595c6c0bc0db43d548df59237446ae041d3e00", + loanScheme: { + id: "MIN150", + minColRatio: "150", + interestRate: "5", + }, + ownerAddress: "bcrt1q39r84tmh4xp7wmg32tnza8j544lynknvy8q2nr", + state: LoanVaultState.IN_LIQUIDATION, + batchCount: 1, + liquidationHeight: 1800, + liquidationPenalty: 5, + batches: [loanBatchFoo], + }, + { + vaultId: + "3f736e4ea13b91ac7dd3633e30a04553570428ad3d1ea8e39ba3162c24ab0b14", + loanScheme: { + id: "MIN150", + minColRatio: "150", + interestRate: "5", + }, + ownerAddress: "bcrt1q39r84tmh4xp7wmg32tnza8j544lynknvy8q2nr", + state: LoanVaultState.IN_LIQUIDATION, + batchCount: 2, + liquidationHeight: 1799, + liquidationPenalty: 5, + batches: [loanBatchFoo, loanBatchBar], + }, + ]; + + const bidHistory: VaultAuctionBatchHistory[] = [ + { + id: "a40dca4568cb17bbcf93cffe25e25a65b028a843ae43c26c33472eb5f5cdd404-0-61913320d0bfd8e10ddeab6d19a68c79394d46aa3f8748d1152687ecee687b43", + key: "a40dca4568cb17bbcf93cffe25e25a65b028a843ae43c26c33472eb5f5cdd404-0", + sort: "0000132a-61913320d0bfd8e10ddeab6d19a68c79394d46aa3f8748d1152687ecee687b43", + address: "mswsMVsyGMj1FzDMbbxw2QW3KvQAv2FKiy", + vaultId: + "a40dca4568cb17bbcf93cffe25e25a65b028a843ae43c26c33472eb5f5cdd404", + index: 0, + from: "001489467aaf77a983e76d1152e62e9e54ad7e49da6c", + amount: "28.37210284", + tokenId: 11, + block: { + hash: "187b623cc714429ba0719262e70b794a6165bcf5a833e25eaf71154c8462b522", + height: 4906, + medianTime: 1641919036, + time: 1641919041, + }, + }, + ]; + + beforeEach(() => { + initialState = { + auctions: [], + bidHistory: [], + hasFetchAuctionsData: false, + }; + }); + + it("should handle initial state", () => { + expect(auctions.reducer(undefined, { type: "unknown" })).toEqual({ + auctions: [], + bidHistory: [], + hasFetchAuctionsData: false, + }); + }); + + it("should handle fetch auctions and set has fetched auction flag", () => { + const action = { type: fetchAuctions.fulfilled, payload: liquidatedVaults }; + const actual = auctions.reducer(initialState, action); + expect(actual.auctions).toStrictEqual(liquidatedVaults); + expect(actual.hasFetchAuctionsData).toStrictEqual(true); + }); + + it("should handle fetch auctions history", () => { + const action = { type: fetchBidHistory.fulfilled, payload: bidHistory }; + const actual = auctions.reducer(initialState, action); + expect(actual.bidHistory).toStrictEqual(bidHistory); + }); + + it("should be able to return loan batches", () => { + const state = { + ...initialState, + auctions: liquidatedVaults, + }; + const actual = getAuctionBatches(state); + expect(actual).toStrictEqual([ + { + ...loanBatchFoo, + collateralTokenSymbols: ["DFI"], + auction: liquidatedVaults[0], + }, + { + ...loanBatchFoo, + collateralTokenSymbols: ["DFI"], + auction: liquidatedVaults[1], + }, + { + ...loanBatchBar, + collateralTokenSymbols: ["DFI"], + auction: liquidatedVaults[1], + }, + ]); + }); +}); diff --git a/walletkit/walletkit-ui/store/block.ts b/walletkit/walletkit-ui/store/block.ts new file mode 100644 index 0000000000..7191f14a73 --- /dev/null +++ b/walletkit/walletkit-ui/store/block.ts @@ -0,0 +1,57 @@ +import { createSlice, PayloadAction } from "@reduxjs/toolkit"; +// TODO(@thedoublejay): see https://github.com/microsoft/TypeScript/issues/47663 +import type {} from "immer"; + +export interface BlockState { + count?: number; + masternodeCount?: number; + lastSync?: string; + connected: boolean; + isPolling: boolean; + tvl?: number; + lastSuccessfulSync?: string; +} + +const initialState: BlockState = { + count: undefined, + masternodeCount: undefined, + lastSync: undefined, + connected: false, + isPolling: false, + tvl: undefined, + lastSuccessfulSync: undefined, +}; + +export const block = createSlice({ + name: "block", + initialState, + reducers: { + updateBlockDetails: ( + state, + action: PayloadAction<{ + count: number; + masternodeCount: number; + lastSync?: string; + lastSuccessfulSync?: string; + tvl?: number; + }>, + ) => { + state.count = action.payload.count; + state.masternodeCount = action.payload.masternodeCount; + const firstSuccessfulSync = + state.lastSuccessfulSync ?? new Date().toString(); + state.lastSuccessfulSync = + action.payload.lastSuccessfulSync != null + ? action.payload.lastSuccessfulSync + : firstSuccessfulSync; + state.lastSync = action.payload.lastSync; // updated even if its not successful (no connection) + state.tvl = action.payload.tvl; + }, + setConnected: (state, action: PayloadAction) => { + state.connected = action.payload; + }, + setPolling: (state, action: PayloadAction) => { + state.isPolling = action.payload; + }, + }, +}); diff --git a/walletkit/walletkit-ui/store/block.unit.ts b/walletkit/walletkit-ui/store/block.unit.ts new file mode 100644 index 0000000000..7077c1cb08 --- /dev/null +++ b/walletkit/walletkit-ui/store/block.unit.ts @@ -0,0 +1,68 @@ +import { block, BlockState } from "./block"; + +describe("block reducer", () => { + let initialState: BlockState; + const date = new Date().toString(); + + beforeEach(() => { + initialState = { + count: 77, + masternodeCount: 10, + lastSuccessfulSync: date, + lastSync: date, + isPolling: false, + connected: false, + tvl: 1, + }; + }); + + it("should handle initial state", () => { + expect(block.reducer(undefined, { type: "unknown" })).toEqual({ + count: undefined, + masternodeCount: undefined, + lastSuccessfulSync: undefined, + connected: false, + isPolling: false, + tvl: undefined, + lastSync: undefined, + }); + }); + + it("should handle updateBlock", () => { + const payload = { + count: 99, + masternodeCount: 0, + lastSuccessfulSync: date, + lastSync: date, + tvl: 1, + }; + const actual = block.reducer( + initialState, + block.actions.updateBlockDetails(payload), + ); + expect(actual).toStrictEqual({ ...initialState, ...payload }); + }); + + it("should handle setConnected", () => { + const actual = block.reducer( + initialState, + block.actions.setConnected(true), + ); + expect(actual).toStrictEqual({ + ...initialState, + count: 77, + isPolling: false, + connected: true, + }); + }); + + it("should handle setPolling", () => { + const actual = block.reducer(initialState, block.actions.setPolling(true)); + expect(actual).toStrictEqual({ + ...initialState, + count: 77, + isPolling: true, + connected: false, + }); + }); +}); diff --git a/walletkit/walletkit-ui/store/futureSwap.ts b/walletkit/walletkit-ui/store/futureSwap.ts new file mode 100644 index 0000000000..6cf6664d62 --- /dev/null +++ b/walletkit/walletkit-ui/store/futureSwap.ts @@ -0,0 +1,123 @@ +import { + FutureData, + GetFutureInfo, +} from "@defichain/jellyfish-api-core/dist/category/account"; +import { WhaleRpcClient } from "@defichain/whale-api-client"; +import { + createAsyncThunk, + createSelector, + createSlice, + PayloadAction, +} from "@reduxjs/toolkit"; +import BigNumber from "bignumber.js"; + +import { selectLoansState } from "./loans"; + +export interface FutureSwapData { + source: { + amount: string; + displaySymbol: string; + isLoanToken: boolean; + symbol: string; + tokenId: string; + }; + destination: { + displaySymbol: string; + isLoanToken: boolean; + symbol: string; + tokenId: string; + }; +} + +export interface FutureSwapState { + futureSwaps: FutureData[]; + executionBlock: number; +} + +const initialState: FutureSwapState = { + futureSwaps: [], + executionBlock: 0, +}; + +export const fetchFutureSwaps = createAsyncThunk( + "wallet/fetchFutureSwaps", + async ({ client, address }: { client: WhaleRpcClient; address: string }) => + client.account.getPendingFutureSwaps(address), +); + +export const fetchExecutionBlock = createAsyncThunk( + "wallet/fetchNextFutureSwapBlock", + async ({ client }: { client: WhaleRpcClient }) => + client.oracle.getFutureSwapBlock(), +); + +export const futureSwaps = createSlice({ + name: "futureSwaps", + initialState, + reducers: {}, + extraReducers: (builder) => { + builder.addCase( + fetchFutureSwaps.fulfilled, + (state, action: PayloadAction) => { + state.futureSwaps = action.payload.values; + }, + ); + builder.addCase( + fetchExecutionBlock.fulfilled, + (state, action: PayloadAction) => { + state.executionBlock = action.payload; + }, + ); + }, +}); + +export const selectFutureSwapState = (state: any): FutureSwapState => + state.futureSwaps; + +export const hasFutureSwap = createSelector( + (state: FutureSwapState) => state.futureSwaps, + (swap): boolean => swap.length > 0, +); + +export const futureSwapSelector = createSelector( + [selectFutureSwapState, selectLoansState], + (futureSwapsState, loans): FutureSwapData[] => + Object.values( + futureSwapsState.futureSwaps.reduce( + (swaps: { [key: string]: FutureSwapData }, swap) => { + const [sourceAmount, sourceSymbol] = swap.source.split("@"); // ['123', 'DUSD'] + const destinationSymbol = swap.destination; + const sourceLoanToken = loans.loanTokens.find( + (token) => token.token.symbol === sourceSymbol, + ); + const destinationLoanToken = loans.loanTokens.find( + (token) => token.token.symbol === destinationSymbol, + ); + const key = `${sourceSymbol}-${destinationSymbol}`; + swaps[key] = { + source: { + amount: + swaps[key] === undefined + ? new BigNumber(sourceAmount).toFixed(8) + : BigNumber.max(new BigNumber(swaps[key].source.amount), 0) + .plus(sourceAmount) + .toFixed(8), + displaySymbol: sourceLoanToken?.token.displaySymbol ?? "", + isLoanToken: sourceLoanToken?.token.displaySymbol !== "DUSD", + symbol: sourceLoanToken?.token.symbol ?? "", + tokenId: sourceLoanToken?.token.id ?? "", + }, + destination: { + displaySymbol: destinationLoanToken?.token.displaySymbol ?? "", + isLoanToken: destinationLoanToken?.token.displaySymbol !== "DUSD", + symbol: destinationLoanToken?.token.symbol ?? "", + tokenId: destinationLoanToken?.token.id ?? "", + }, + }; + + return swaps; + }, + {}, + ), + ), +); diff --git a/walletkit/walletkit-ui/store/futureSwap.unit.ts b/walletkit/walletkit-ui/store/futureSwap.unit.ts new file mode 100644 index 0000000000..833fb06e9b --- /dev/null +++ b/walletkit/walletkit-ui/store/futureSwap.unit.ts @@ -0,0 +1,52 @@ +import { GetFutureInfo } from "@defichain/jellyfish-api-core/dist/category/account"; + +import { + fetchExecutionBlock, + fetchFutureSwaps, + futureSwaps, + FutureSwapState, +} from "./futureSwap"; + +describe("futureSwap reducer", () => { + let initialState: FutureSwapState; + + beforeEach(() => { + initialState = { + futureSwaps: [], + executionBlock: 0, + }; + }); + + it("should handle initial state", () => { + expect(futureSwaps.reducer(undefined, { type: "unknown" })).toEqual({ + futureSwaps: [], + executionBlock: 0, + }); + }); + + it("should handle fetchExecutionBlock", () => { + const action = { type: fetchExecutionBlock.fulfilled, payload: 10 }; + const actual = futureSwaps.reducer(initialState, action); + expect(actual.executionBlock).toStrictEqual(10); + }); + + it("should handle fetchFutureSwaps", () => { + const getFutureInfo: GetFutureInfo = { + owner: "bcrt1qgnmfwckutkvekgulky92r3csyct0z064yvjax5", + values: [ + { + source: "tf1qn0jv4xh60ryx4wyq8wvf0w30f77gqx3f3etyvt", + destination: "tf1qn0jv4xh60ryx4wyq8wvf0w30f77gqx3f3etyvt", + }, + { + source: "tf1qn0jv4xh60ryx4wyq8wvf0w30f77gqx3f3etyvt", + destination: "tf1qn0jv4xh60ryx4wyq8wvf0w30f77gqx3f3etyvt", + }, + ], + }; + + const action = { type: fetchFutureSwaps.fulfilled, payload: getFutureInfo }; + const actual = futureSwaps.reducer(initialState, action); + expect(actual.futureSwaps).toStrictEqual(getFutureInfo.values); + }); +}); diff --git a/walletkit/walletkit-ui/store/index.ts b/walletkit/walletkit-ui/store/index.ts new file mode 100644 index 0000000000..e6670def61 --- /dev/null +++ b/walletkit/walletkit-ui/store/index.ts @@ -0,0 +1,10 @@ +export * from "./auctions"; +export * from "./block"; +export * from "./futureSwap"; +export * from "./loans"; +export * from "./ocean"; +export * from "./transaction_queue"; +export * from "./types"; +export * from "./userPreferences"; +export * from "./wallet"; +export * from "./website"; diff --git a/walletkit/walletkit-ui/store/loans.ts b/walletkit/walletkit-ui/store/loans.ts new file mode 100644 index 0000000000..718ddd9e1a --- /dev/null +++ b/walletkit/walletkit-ui/store/loans.ts @@ -0,0 +1,232 @@ +import { WhaleApiClient } from "@defichain/whale-api-client"; +import { + CollateralToken, + LoanScheme, + LoanToken, + LoanVaultActive, + LoanVaultLiquidated, + LoanVaultState, +} from "@defichain/whale-api-client/dist/api/loan"; +import { ActivePrice } from "@defichain/whale-api-client/dist/api/prices"; +import { + createAsyncThunk, + createSelector, + createSlice, + PayloadAction, +} from "@reduxjs/toolkit"; +import BigNumber from "bignumber.js"; + +import { useVaultStatus } from "../hooks"; +import { VaultStatus } from "./types"; + +export type LoanVault = LoanVaultActive | LoanVaultLiquidated; + +export interface LoanPaymentTokenActivePrices { + [key: string]: ActivePrice; +} + +export interface LoansState { + vaults: LoanVault[]; + loanTokens: LoanToken[]; + loanSchemes: LoanScheme[]; + collateralTokens: CollateralToken[]; + loanPaymentTokenActivePrices: LoanPaymentTokenActivePrices; + hasFetchedVaultsData: boolean; + hasFetchedLoansData: boolean; + hasFetchedLoanSchemes: boolean; +} + +const initialState: LoansState = { + vaults: [], + loanTokens: [], + loanSchemes: [], + collateralTokens: [], + loanPaymentTokenActivePrices: {}, + hasFetchedVaultsData: false, + hasFetchedLoansData: false, + hasFetchedLoanSchemes: false, +}; + +// TODO (Harsh) Manage pagination for all api +export const fetchVaults = createAsyncThunk( + "wallet/fetchVaults", + async ({ + size = 200, + address, + client, + }: { + size?: number; + address: string; + client: WhaleApiClient; + }) => client.address.listVault(address, size), +); + +export const fetchLoanTokens = createAsyncThunk( + "wallet/fetchLoanTokens", + async ({ size = 200, client }: { size?: number; client: WhaleApiClient }) => + client.loan.listLoanToken(size), +); + +export const fetchLoanSchemes = createAsyncThunk( + "wallet/fetchLoanSchemes", + async ({ size = 50, client }: { size?: number; client: WhaleApiClient }) => + client.loan.listScheme(size), +); + +export const fetchCollateralTokens = createAsyncThunk( + "wallet/fetchCollateralTokens", + async ({ size = 50, client }: { size?: number; client: WhaleApiClient }) => + client.loan.listCollateralToken(size), +); + +export const fetchPrice = createAsyncThunk( + "wallet/fetchPrice", + async ({ + client, + token, + currency, + }: { + token: string; + currency: string; + client: WhaleApiClient; + }) => { + const activePrices = await client.prices.getFeedActive(token, currency, 1); + return activePrices[0]; + }, +); + +export const loans = createSlice({ + name: "loans", + initialState, + reducers: { + setHasFetchedVaultsData: (state, action: PayloadAction) => { + state.hasFetchedVaultsData = action.payload; + }, + }, + extraReducers: (builder) => { + builder.addCase( + fetchVaults.fulfilled, + (state, action: PayloadAction) => { + state.vaults = action.payload; + state.hasFetchedVaultsData = true; + }, + ); + builder.addCase( + fetchLoanTokens.fulfilled, + (state, action: PayloadAction) => { + state.loanTokens = action.payload; + state.hasFetchedLoansData = true; + }, + ); + builder.addCase( + fetchLoanSchemes.fulfilled, + (state, action: PayloadAction) => { + state.loanSchemes = action.payload; + state.hasFetchedLoanSchemes = true; + }, + ); + builder.addCase( + fetchCollateralTokens.fulfilled, + (state, action: PayloadAction) => { + state.collateralTokens = action.payload; + }, + ); + builder.addCase( + fetchPrice.fulfilled, + (state, action: PayloadAction) => { + state.loanPaymentTokenActivePrices = { + ...state.loanPaymentTokenActivePrices, + ...{ + [action.payload.key]: action.payload, + }, + }; + }, + ); + }, +}); + +export const selectLoansState = (state: any): LoansState => state.loans; + +export const ascColRatioLoanScheme = createSelector( + (state: LoansState) => state.loanSchemes, + (schemes) => + schemes + .map((c) => c) + .sort((a, b) => + new BigNumber(a.minColRatio).minus(b.minColRatio).toNumber(), + ), +); + +export const loanTokensSelector = createSelector( + (state: LoansState) => state.loanTokens, + (loanTokens) => loanTokens, +); + +const selectTokenId = (state: LoansState, tokenId: string): string => tokenId; + +export const loanTokenByTokenId = createSelector( + [selectTokenId, loanTokensSelector], + (tokenId, loanTokens) => + loanTokens.find((loanToken) => loanToken.token.id === tokenId), +); + +export const loanPaymentTokenActivePrices = createSelector( + (state: LoansState) => state.loanPaymentTokenActivePrices, + (activePrices) => activePrices, +); + +export const vaultsSelector = createSelector( + (state: LoansState) => state.vaults, + (vaults) => { + const order = { + [VaultStatus.NearLiquidation]: 1, + [VaultStatus.AtRisk]: 2, + [VaultStatus.Healthy]: 3, + [VaultStatus.Liquidated]: 4, + [VaultStatus.Ready]: 5, + [VaultStatus.Halted]: 6, + [VaultStatus.Empty]: 7, + [VaultStatus.Unknown]: 8, + }; + + return vaults + .map((vault) => { + if (vault.state === LoanVaultState.IN_LIQUIDATION) { + return { + ...vault, + vaultState: VaultStatus.Liquidated, + }; + } + + const colRatio = new BigNumber(vault.collateralRatio); + const minColRatio = new BigNumber(vault.loanScheme.minColRatio); + const totalLoanValue = new BigNumber(vault.loanValue); + const totalCollateralValue = new BigNumber(vault.collateralValue); + const vaultState = useVaultStatus( + vault.state, + colRatio, + minColRatio, + totalLoanValue, + totalCollateralValue, + ); + return { + ...vault, + vaultState: vaultState.status, + }; + }) + .sort((a, b) => order[a.vaultState] - order[b.vaultState]); + }, +); + +//* Filter vaults that will be removed with Total Portfolio Amount +export const activeVaultsSelector = createSelector( + vaultsSelector, + (vaults) => + vaults.filter((value: LoanVault) => + [ + LoanVaultState.ACTIVE, + LoanVaultState.MAY_LIQUIDATE, + LoanVaultState.FROZEN, + ].includes(value.state), + ) as LoanVaultActive[], +); diff --git a/walletkit/walletkit-ui/store/loans.unit.ts b/walletkit/walletkit-ui/store/loans.unit.ts new file mode 100644 index 0000000000..23969f7389 --- /dev/null +++ b/walletkit/walletkit-ui/store/loans.unit.ts @@ -0,0 +1,623 @@ +import { + CollateralToken, + LoanScheme, + LoanToken, + LoanVaultLiquidated, + LoanVaultState, +} from "@defichain/whale-api-client/dist/api/loan"; + +import { + ascColRatioLoanScheme, + fetchCollateralTokens, + fetchLoanSchemes, + fetchLoanTokens, + fetchVaults, + loans, + LoansState, + loanTokenByTokenId, + loanTokensSelector, + LoanVault, + vaultsSelector, +} from "./loans"; +import { VaultStatus } from "./types"; + +describe("loans reducer", () => { + let initialState: LoansState; + const vault: LoanVault = { + vaultId: "eee84f2cc56bbc51a42eaf302b76d4d1250b58b943829ee82f2fa9a46a9e4319", + loanScheme: { + id: "MIN150", + minColRatio: "150", + interestRate: "5", + }, + ownerAddress: "bcrt1q39r84tmh4xp7wmg32tnza8j544lynknvy8q2nr", + state: LoanVaultState.ACTIVE, + informativeRatio: "9999.94300032", + collateralRatio: "10000", + collateralValue: "100", + loanValue: "1.0000057", + interestValue: "0.0000057", + collateralAmounts: [ + { + id: "0", + amount: "1.00000000", + symbol: "DFI", + symbolKey: "DFI", + name: "Default Defi token", + displaySymbol: "DFI", + }, + ], + loanAmounts: [ + { + id: "14", + amount: "1.00000570", + symbol: "DUSD", + symbolKey: "DUSD", + name: "Decentralized USD", + displaySymbol: "DUSD", + }, + { + id: "13", + amount: "0.00000001", + symbol: "TD10", + symbolKey: "TD10", + name: "Decentralized TD10", + displaySymbol: "dTD10", + }, + ], + interestAmounts: [ + { + id: "14", + amount: "0.00000570", + symbol: "DUSD", + symbolKey: "DUSD", + name: "Decentralized USD", + displaySymbol: "DUSD", + }, + { + id: "13", + amount: "0.00000000", + symbol: "TD10", + symbolKey: "TD10", + name: "Decentralized TD10", + displaySymbol: "dTD10", + }, + ], + }; + const loanTokens: LoanToken[] = [ + { + tokenId: + "a3a124bf5a6c37fe8d293b45bf32a16e412d06c376d0a042078279564c07ac2e", + token: { + id: "10", + symbol: "TD10", + symbolKey: "TD10", + name: "Decentralized TD10", + decimal: 8, + limit: "0", + mintable: true, + tradeable: true, + isDAT: true, + isLPS: false, + finalized: false, + minted: "0.0001027", + creation: { + tx: "a3a124bf5a6c37fe8d293b45bf32a16e412d06c376d0a042078279564c07ac2e", + height: 128, + }, + destruction: { + tx: "0000000000000000000000000000000000000000000000000000000000000000", + height: -1, + }, + collateralAddress: "bcrt1qyrfrpadwgw7p5eh3e9h3jmu4kwlz4prx73cqny", + displaySymbol: "dTD10", + isLoanToken: true, + }, + interest: "1.5", + fixedIntervalPriceId: "TD10/USD", + }, + { + tokenId: + "b99d32217b8fbe8872015c1a376f745a94372f061a0fb88c9b212876e4f158f5", + token: { + id: "14", + symbol: "DUSD", + symbolKey: "DUSD", + name: "Decentralized USD", + decimal: 8, + limit: "0", + mintable: true, + tradeable: true, + isDAT: true, + isLPS: false, + finalized: false, + minted: "20540", + creation: { + tx: "b99d32217b8fbe8872015c1a376f745a94372f061a0fb88c9b212876e4f158f5", + height: 128, + }, + destruction: { + tx: "0000000000000000000000000000000000000000000000000000000000000000", + height: -1, + }, + collateralAddress: "bcrt1qyrfrpadwgw7p5eh3e9h3jmu4kwlz4prx73cqny", + displaySymbol: "DUSD", + isLoanToken: true, + }, + interest: "0", + fixedIntervalPriceId: "DUSD/USD", + }, + { + tokenId: + "ffbaea57f155a36700c65a018aafe5e7d9984416339fb623df887f1a82b12142", + token: { + id: "11", + symbol: "TR50", + symbolKey: "TR50", + name: "Decentralized TR50", + decimal: 8, + limit: "0", + mintable: true, + tradeable: true, + isDAT: true, + isLPS: false, + finalized: false, + minted: "10.27", + creation: { + tx: "ffbaea57f155a36700c65a018aafe5e7d9984416339fb623df887f1a82b12142", + height: 128, + }, + destruction: { + tx: "0000000000000000000000000000000000000000000000000000000000000000", + height: -1, + }, + collateralAddress: "bcrt1qyrfrpadwgw7p5eh3e9h3jmu4kwlz4prx73cqny", + displaySymbol: "dTR50", + isLoanToken: true, + }, + interest: "3", + fixedIntervalPriceId: "TR50/USD", + }, + ]; + const loanSchemes: LoanScheme[] = [ + { + id: "MIN10000", + minColRatio: "1000", + interestRate: "0.5", + }, + { + id: "MIN150", + minColRatio: "150", + interestRate: "5", + }, + { + id: "MIN175", + minColRatio: "175", + interestRate: "3", + }, + { + id: "MIN200", + minColRatio: "200", + interestRate: "2", + }, + { + id: "MIN350", + minColRatio: "350", + interestRate: "1.5", + }, + { + id: "MIN500", + minColRatio: "500", + interestRate: "1", + }, + ]; + + beforeEach(() => { + initialState = { + vaults: [], + loanTokens: [], + loanSchemes: [], + collateralTokens: [], + loanPaymentTokenActivePrices: {}, + hasFetchedLoanSchemes: false, + hasFetchedVaultsData: false, + hasFetchedLoansData: false, + }; + }); + + it("should handle initial state", () => { + expect(loans.reducer(undefined, { type: "unknown" })).toEqual({ + vaults: [], + loanTokens: [], + loanSchemes: [], + collateralTokens: [], + loanPaymentTokenActivePrices: {}, + hasFetchedVaultsData: false, + hasFetchedLoansData: false, + hasFetchedLoanSchemes: false, + }); + }); + + it("should handle fetch vaults", () => { + const action = { type: fetchVaults.fulfilled, payload: [vault] }; + const actual = loans.reducer(initialState, action); + expect(actual.vaults).toStrictEqual([vault]); + }); + + it("should handle fetch loan tokens", () => { + const action = { type: fetchLoanTokens.fulfilled, payload: loanTokens }; + const actual = loans.reducer(initialState, action); + expect(actual.loanTokens).toStrictEqual(loanTokens); + }); + + it("should handle fetch loan schemes", () => { + const action = { type: fetchLoanSchemes.fulfilled, payload: loanSchemes }; + const actual = loans.reducer(initialState, action); + expect(actual.loanSchemes).toStrictEqual(loanSchemes); + }); + + it("should handle fetch collateral tokens", () => { + const collateralTokens: CollateralToken[] = [ + { + tokenId: + "08987c2d1f3d7d5a18a331c4a173a85be34cf5d2438a3e51a2ed4ed2779a6279", + token: { + id: "8", + symbol: "CS25", + symbolKey: "CS25", + name: "Playground CS25", + decimal: 8, + limit: "0", + mintable: true, + tradeable: true, + isDAT: true, + isLPS: false, + finalized: false, + minted: "100000000", + creation: { + tx: "37e2279b80e68f55fe1ccf9920a084731cd08e331a5ee6f7769759263e66bdcb", + height: 118, + }, + destruction: { + tx: "0000000000000000000000000000000000000000000000000000000000000000", + height: -1, + }, + collateralAddress: "mswsMVsyGMj1FzDMbbxw2QW3KvQAv2FKiy", + displaySymbol: "dCS25", + isLoanToken: false, + }, + factor: "1", + activateAfterBlock: 130, + fixedIntervalPriceId: "CS25/USD", + }, + { + tokenId: + "0b990af4ede825e3b626ac3eaa72111babf0ee5e188e66ce503415e0d3f88031", + token: { + id: "3", + symbol: "USDT", + symbolKey: "USDT", + name: "Playground USDT", + decimal: 8, + limit: "0", + mintable: true, + tradeable: true, + isDAT: true, + isLPS: false, + finalized: false, + minted: "1000000000", + creation: { + tx: "3fba5bf3426acbe9e3aadc9827ec8eb646ee6a2e6b09eb41ce69bddfe054d03a", + height: 107, + }, + destruction: { + tx: "0000000000000000000000000000000000000000000000000000000000000000", + height: -1, + }, + collateralAddress: "mswsMVsyGMj1FzDMbbxw2QW3KvQAv2FKiy", + displaySymbol: "dUSDT", + isLoanToken: false, + }, + factor: "1", + activateAfterBlock: 129, + fixedIntervalPriceId: "USDT/USD", + }, + { + tokenId: + "11c000d76c6d45f069630ffb3534d69f1b0e1d75a1f97d9bb3fcfaa051116126", + token: { + id: "9", + symbol: "CR50", + symbolKey: "CR50", + name: "Playground CR50", + decimal: 8, + limit: "0", + mintable: true, + tradeable: true, + isDAT: true, + isLPS: false, + finalized: false, + minted: "100000000", + creation: { + tx: "2f35eb08a993b052cbb60fb27062c6ff6f88015c92566a243d0092c267a31462", + height: 120, + }, + destruction: { + tx: "0000000000000000000000000000000000000000000000000000000000000000", + height: -1, + }, + collateralAddress: "mswsMVsyGMj1FzDMbbxw2QW3KvQAv2FKiy", + displaySymbol: "dCR50", + isLoanToken: false, + }, + factor: "1", + activateAfterBlock: 130, + fixedIntervalPriceId: "CR50/USD", + }, + ]; + const action = { + type: fetchCollateralTokens.fulfilled, + payload: collateralTokens, + }; + const actual = loans.reducer(initialState, action); + expect(actual.collateralTokens).toStrictEqual(collateralTokens); + }); + + it("should be able to select loan schemes with ascending collateralization ratio", () => { + const state = { + ...initialState, + loanSchemes, + }; + const actual = ascColRatioLoanScheme(state); + expect(actual).toStrictEqual([ + { + id: "MIN150", + minColRatio: "150", + interestRate: "5", + }, + { + id: "MIN175", + minColRatio: "175", + interestRate: "3", + }, + { + id: "MIN200", + minColRatio: "200", + interestRate: "2", + }, + { + id: "MIN350", + minColRatio: "350", + interestRate: "1.5", + }, + { + id: "MIN500", + minColRatio: "500", + interestRate: "1", + }, + { + id: "MIN10000", + minColRatio: "1000", + interestRate: "0.5", + }, + ]); + }); + + it("should be able to select loans token that returns DUSD with active price", () => { + const state = { + ...initialState, + loanTokens, + }; + const loanTokensWithDUSDActivePrice: LoanToken[] = [ + { + tokenId: + "a3a124bf5a6c37fe8d293b45bf32a16e412d06c376d0a042078279564c07ac2e", + token: { + id: "10", + symbol: "TD10", + symbolKey: "TD10", + name: "Decentralized TD10", + decimal: 8, + limit: "0", + mintable: true, + tradeable: true, + isDAT: true, + isLPS: false, + finalized: false, + minted: "0.0001027", + creation: { + tx: "a3a124bf5a6c37fe8d293b45bf32a16e412d06c376d0a042078279564c07ac2e", + height: 128, + }, + destruction: { + tx: "0000000000000000000000000000000000000000000000000000000000000000", + height: -1, + }, + collateralAddress: "bcrt1qyrfrpadwgw7p5eh3e9h3jmu4kwlz4prx73cqny", + displaySymbol: "dTD10", + isLoanToken: true, + }, + interest: "1.5", + fixedIntervalPriceId: "TD10/USD", + }, + { + tokenId: + "b99d32217b8fbe8872015c1a376f745a94372f061a0fb88c9b212876e4f158f5", + token: { + id: "14", + symbol: "DUSD", + symbolKey: "DUSD", + name: "Decentralized USD", + decimal: 8, + limit: "0", + mintable: true, + tradeable: true, + isDAT: true, + isLPS: false, + finalized: false, + minted: "20540", + creation: { + tx: "b99d32217b8fbe8872015c1a376f745a94372f061a0fb88c9b212876e4f158f5", + height: 128, + }, + destruction: { + tx: "0000000000000000000000000000000000000000000000000000000000000000", + height: -1, + }, + collateralAddress: "bcrt1qyrfrpadwgw7p5eh3e9h3jmu4kwlz4prx73cqny", + displaySymbol: "DUSD", + isLoanToken: true, + }, + interest: "0", + fixedIntervalPriceId: "DUSD/USD", + }, + { + tokenId: + "ffbaea57f155a36700c65a018aafe5e7d9984416339fb623df887f1a82b12142", + token: { + id: "11", + symbol: "TR50", + symbolKey: "TR50", + name: "Decentralized TR50", + decimal: 8, + limit: "0", + mintable: true, + tradeable: true, + isDAT: true, + isLPS: false, + finalized: false, + minted: "10.27", + creation: { + tx: "ffbaea57f155a36700c65a018aafe5e7d9984416339fb623df887f1a82b12142", + height: 128, + }, + destruction: { + tx: "0000000000000000000000000000000000000000000000000000000000000000", + height: -1, + }, + collateralAddress: "bcrt1qyrfrpadwgw7p5eh3e9h3jmu4kwlz4prx73cqny", + displaySymbol: "dTR50", + isLoanToken: true, + }, + interest: "3", + fixedIntervalPriceId: "TR50/USD", + }, + ]; + const actual = loanTokensSelector(state); + expect(actual).toStrictEqual(loanTokensWithDUSDActivePrice); + }); + + it("should be able to select loan token by token ID", () => { + const state = { + ...initialState, + loanTokens, + }; + const actual = loanTokenByTokenId(state, "14"); + expect(actual).toStrictEqual({ + tokenId: + "b99d32217b8fbe8872015c1a376f745a94372f061a0fb88c9b212876e4f158f5", + token: { + id: "14", + symbol: "DUSD", + symbolKey: "DUSD", + name: "Decentralized USD", + decimal: 8, + limit: "0", + mintable: true, + tradeable: true, + isDAT: true, + isLPS: false, + finalized: false, + minted: "20540", + creation: { + tx: "b99d32217b8fbe8872015c1a376f745a94372f061a0fb88c9b212876e4f158f5", + height: 128, + }, + destruction: { + tx: "0000000000000000000000000000000000000000000000000000000000000000", + height: -1, + }, + collateralAddress: "bcrt1qyrfrpadwgw7p5eh3e9h3jmu4kwlz4prx73cqny", + displaySymbol: "DUSD", + isLoanToken: true, + }, + interest: "0", + fixedIntervalPriceId: "DUSD/USD", + }); + }); + + it("should be able to select vaults regardless of vault state", () => { + const liquidatedVault: LoanVaultLiquidated & { vaultState: VaultStatus } = { + vaultId: + "eee84f2cc56bbc51a42eaf302b76d4d1250b58b943829ee82f2fa9a46a9e4319", + loanScheme: { + id: "MIN150", + minColRatio: "150", + interestRate: "5", + }, + ownerAddress: "bcrt1q39r84tmh4xp7wmg32tnza8j544lynknvy8q2nr", + state: LoanVaultState.IN_LIQUIDATION, + vaultState: VaultStatus.Liquidated, + liquidationHeight: 1, + liquidationPenalty: 1, + batchCount: 1, + batches: [], + }; + const state = { + ...initialState, + vaults: [liquidatedVault], + }; + const actual = vaultsSelector(state); + expect(actual).toStrictEqual([liquidatedVault]); + }); + + it("should be able to select vaults that returns DUSD loan and interest with active price", () => { + const state = { + ...initialState, + vaults: [vault], + }; + const actual = vaultsSelector(state); + expect(actual).toStrictEqual([ + { + ...vault, + loanAmounts: [ + { + id: "14", + amount: "1.00000570", + symbol: "DUSD", + symbolKey: "DUSD", + name: "Decentralized USD", + displaySymbol: "DUSD", + }, + { + id: "13", + amount: "0.00000001", + symbol: "TD10", + symbolKey: "TD10", + name: "Decentralized TD10", + displaySymbol: "dTD10", + }, + ], + interestAmounts: [ + { + id: "14", + amount: "0.00000570", + symbol: "DUSD", + symbolKey: "DUSD", + name: "Decentralized USD", + displaySymbol: "DUSD", + }, + { + id: "13", + amount: "0.00000000", + symbol: "TD10", + symbolKey: "TD10", + name: "Decentralized TD10", + displaySymbol: "dTD10", + }, + ], + vaultState: "HEALTHY", + }, + ]); + }); +}); diff --git a/walletkit/walletkit-ui/store/ocean.ts b/walletkit/walletkit-ui/store/ocean.ts new file mode 100644 index 0000000000..93235bacd5 --- /dev/null +++ b/walletkit/walletkit-ui/store/ocean.ts @@ -0,0 +1,76 @@ +import { CTransactionSegWit } from "@defichain/jellyfish-transaction"; +import { createSelector, createSlice, PayloadAction } from "@reduxjs/toolkit"; +// TODO(@thedoublejay): see https://github.com/microsoft/TypeScript/issues/47663 +import type {} from "reselect"; + +export enum TransactionStatusCode { + success = 200, + pending = 202, +} + +export interface OceanTransaction { + broadcasted: boolean; + tx: CTransactionSegWit; + title?: string; + drawerMessages?: { + preparing?: string; + waiting?: string; + complete?: string; + }; + submitButtonLabel?: string; + onBroadcast?: () => any; + onConfirmation?: () => any; + onError?: () => any; + oceanStatusCode?: TransactionStatusCode; +} + +export interface OceanState { + transactions: OceanTransaction[]; + height: number; + err?: Error; +} + +const initialState: OceanState = { + transactions: [], + height: 0, + err: undefined, +}; + +export const ocean = createSlice({ + name: "ocean", + initialState, + reducers: { + setHeight: (state, action: PayloadAction) => { + state.height = action.payload; + }, + queueTransaction: ( + state, + action: PayloadAction>, + ) => { + state.transactions = [ + ...state.transactions, + { + ...action.payload, + broadcasted: false, + }, + ]; + }, + setError: (state, action: PayloadAction) => { + state.err = action.payload; + }, + popTransaction: (state) => { + state.transactions.shift(); + state.transactions = [...state.transactions]; + }, + }, +}); + +export const firstTransactionSelector = createSelector( + (state: OceanState) => state.transactions, + (transactions) => transactions[0], +); + +export const hasOceanTXQueued = createSelector( + (state: OceanState) => state.transactions, + (transactions) => transactions.length > 0, +); diff --git a/walletkit/walletkit-ui/store/ocean.unit.ts b/walletkit/walletkit-ui/store/ocean.unit.ts new file mode 100644 index 0000000000..5329265fe0 --- /dev/null +++ b/walletkit/walletkit-ui/store/ocean.unit.ts @@ -0,0 +1,86 @@ +import { CTransactionSegWit } from "@defichain/jellyfish-transaction"; +import { SmartBuffer } from "smart-buffer"; + +import { ocean, OceanState, OceanTransaction } from "./ocean"; + +describe("ocean reducer", () => { + let initialState: OceanState; + + beforeEach(() => { + initialState = { + transactions: [], + height: 0, + err: undefined, + }; + }); + + it("should handle initial state", () => { + expect(ocean.reducer(undefined, { type: "unknown" })).toEqual({ + transactions: [], + err: undefined, + height: 0, + }); + }); + + it("should handle queueTransaction and popTransaction", () => { + const v2 = + "020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff050393700500ffffffff038260498a040000001976a9143db7aeb218455b697e94f6ff00c548e72221231d88ac7e67ce1d0000000017a914dd7730517e0e4969b4e43677ff5bee682e53420a870000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000"; + const buffer = SmartBuffer.fromBuffer(Buffer.from(v2, "hex")); + const signed = new CTransactionSegWit(buffer); + const payload: Omit = { + title: "Sending", + tx: signed, + }; + const addedTransaction = ocean.reducer( + initialState, + ocean.actions.queueTransaction(payload), + ); + expect(addedTransaction).toStrictEqual({ + transactions: [ + { + ...payload, + broadcasted: false, + }, + ], + err: undefined, + height: 0, + }); + const actual = ocean.reducer( + addedTransaction, + ocean.actions.queueTransaction(payload), + ); + + const pop = ocean.reducer(actual, ocean.actions.popTransaction()); + expect(pop).toStrictEqual({ + transactions: [ + { + ...payload, + broadcasted: false, + }, + ], + err: undefined, + height: 0, + }); + const removed = ocean.reducer(pop, ocean.actions.popTransaction()); + expect(removed).toStrictEqual({ + transactions: [], + err: undefined, + height: 0, + }); + }); + + it("should handle setError", () => { + const err = new Error("An error has occurred"); + const actual = ocean.reducer(initialState, ocean.actions.setError(err)); + expect(actual).toStrictEqual({ transactions: [], err, height: 0 }); + }); + + it("should setHeight", () => { + const actual = ocean.reducer(initialState, ocean.actions.setHeight(77)); + expect(actual).toStrictEqual({ + transactions: [], + err: undefined, + height: 77, + }); + }); +}); diff --git a/walletkit/walletkit-ui/store/transaction_queue.ts b/walletkit/walletkit-ui/store/transaction_queue.ts new file mode 100644 index 0000000000..34747c7e8f --- /dev/null +++ b/walletkit/walletkit-ui/store/transaction_queue.ts @@ -0,0 +1,57 @@ +import { CTransactionSegWit } from "@defichain/jellyfish-transaction"; +import { WhaleWalletAccount } from "@defichain/whale-api-wallet"; +import { createSelector, createSlice, PayloadAction } from "@reduxjs/toolkit"; +// TODO(@thedoublejay): see https://github.com/microsoft/TypeScript/issues/47663 +import type {} from "reselect"; + +export interface DfTxSigner { + sign: (account: WhaleWalletAccount) => Promise; + title?: string; + description?: string; + drawerMessages?: { + preparing?: string; + waiting?: string; + complete?: string; + }; + onBroadcast?: () => any; + onConfirmation?: () => any; + onError?: () => any; + submitButtonLabel?: string; +} + +export interface TransactionQueue { + transactions: DfTxSigner[]; + err?: Error; +} + +const initialState: TransactionQueue = { + transactions: [], + err: undefined, +}; + +export const transactionQueue = createSlice({ + name: "tx_queue", + initialState, + reducers: { + push: (state, action: PayloadAction) => { + state.transactions = [...state.transactions, action.payload]; + state.err = undefined; + }, + pop: (state) => { + state.transactions.shift(); + state.transactions = [...state.transactions]; + }, + setError: (state, action: PayloadAction) => { + state.err = action.payload; + }, + }, +}); + +export const first = createSelector( + (state: TransactionQueue) => state.transactions, + (transactions) => transactions[0], +); +export const hasTxQueued = createSelector( + (state: TransactionQueue) => state.transactions, + (transactions) => transactions.length > 0, +); diff --git a/walletkit/walletkit-ui/store/transaction_queue.unit.ts b/walletkit/walletkit-ui/store/transaction_queue.unit.ts new file mode 100644 index 0000000000..93aacaf3dd --- /dev/null +++ b/walletkit/walletkit-ui/store/transaction_queue.unit.ts @@ -0,0 +1,58 @@ +import { + DfTxSigner, + first, + hasTxQueued, + TransactionQueue, + transactionQueue, +} from "./transaction_queue"; + +describe("transaction reducer", () => { + let initialState: TransactionQueue; + + beforeEach(() => { + initialState = { + transactions: [], + err: undefined, + }; + }); + + it("should handle initial state", () => { + expect(transactionQueue.reducer(undefined, { type: "unknown" })).toEqual({ + transactions: [], + }); + }); + + it("should handle push and pop", () => { + const payload: DfTxSigner = { + sign: null as any, + title: "Sample Transaction", + }; + const actual = transactionQueue.reducer( + initialState, + transactionQueue.actions.push(payload), + ); + expect(actual).toStrictEqual({ transactions: [payload], err: undefined }); + const pop = transactionQueue.reducer( + initialState, + transactionQueue.actions.pop(), + ); + expect(pop).toStrictEqual({ transactions: [], err: undefined }); + }); + + it("should able to select first and check queue transaction", () => { + const payload: DfTxSigner = { + sign: null as any, + title: "Sample Transaction", + }; + const hasQueue = hasTxQueued({ + ...initialState, + transactions: [payload], + }); + expect(hasQueue).toStrictEqual(true); + const actual = first({ + ...initialState, + transactions: [payload], + }); + expect(actual).toStrictEqual(payload); + }); +}); diff --git a/walletkit/walletkit-ui/store/types/VaultStatus.ts b/walletkit/walletkit-ui/store/types/VaultStatus.ts new file mode 100644 index 0000000000..1fd385ea6f --- /dev/null +++ b/walletkit/walletkit-ui/store/types/VaultStatus.ts @@ -0,0 +1,33 @@ +import BigNumber from "bignumber.js"; + +export interface CollateralizationRatioProps { + colRatio: BigNumber; + minColRatio: BigNumber; + totalLoanAmount: BigNumber; + totalCollateralValue?: BigNumber; +} + +export interface CollateralizationRatioStats { + atRiskThreshold: BigNumber; + liquidatedThreshold: BigNumber; + isInLiquidation: boolean; + isAtRisk: boolean; + isHealthy: boolean; + isReady: boolean; +} + +export enum VaultStatus { + Empty = "EMPTY", + Ready = "READY", + Healthy = "HEALTHY", + AtRisk = "AT RISK", + Halted = "HALTED", + NearLiquidation = "NEAR LIQUIDATION", + Liquidated = "IN LIQUIDATION", + Unknown = "UNKNOWN", +} + +export interface VaultHealthItem { + vaultStats: CollateralizationRatioStats; + status: VaultStatus; +} diff --git a/walletkit/walletkit-ui/store/types/index.ts b/walletkit/walletkit-ui/store/types/index.ts new file mode 100644 index 0000000000..5361bb4a66 --- /dev/null +++ b/walletkit/walletkit-ui/store/types/index.ts @@ -0,0 +1 @@ +export * from "./VaultStatus"; diff --git a/walletkit/walletkit-ui/store/userPreferences.ts b/walletkit/walletkit-ui/store/userPreferences.ts new file mode 100644 index 0000000000..4e58fe9850 --- /dev/null +++ b/walletkit/walletkit-ui/store/userPreferences.ts @@ -0,0 +1,130 @@ +/* eslint-disable */ + +import { + createAsyncThunk, + createSelector, + createSlice, + PayloadAction, +} from "@reduxjs/toolkit"; +import { EnvironmentNetwork } from "@waveshq/walletkit-core"; + +export interface LabeledAddress { + [address: string]: LocalAddress; +} + +export interface LocalAddress { + address: string; + label: string; + isMine: boolean; + isFavourite?: boolean; +} + +export interface UserPreferences { + addresses: LabeledAddress; + addressBook: LabeledAddress; +} + +const prepopulateField = (addresses: LabeledAddress): LocalAddress[] => { + const _addresses: LabeledAddress = { ...addresses }; + + // pre-populate address and isFavourite flag for older app version, used for UI data model only + for (const address in addresses) { + if (addresses[address].address === undefined) { + const _address = { + ...addresses[address], + address, + isFavourite: false, + }; + _addresses[address] = _address; + } + } + return Object.values(_addresses); +}; + +const initialState: UserPreferences = { + addresses: {}, + addressBook: {}, +}; + +export const fetchUserPreferences = createAsyncThunk( + "userPreferences/fetchUserPreferences", + // TODO @julio replace with type + async (network: EnvironmentNetwork, localStorage: any) => + await localStorage.getUserPreferences(network), +); + +export const setUserPreferences = createAsyncThunk( + "userPreferences/setUserPreferences", + async ({ + network, + preferences, + localStorage, + }: { + network: EnvironmentNetwork; + preferences: UserPreferences; + // TODO @julio replace with type + localStorage: any; + }) => { + await localStorage.setUserPreferences(network, preferences); + }, +); + +export const setAddresses = createAsyncThunk( + "userPreferences/setAddresses", + async (addresses: LabeledAddress) => addresses, +); + +export const setAddressBook = createAsyncThunk( + "userPreferences/setAddressBook", + async (addressBook: LabeledAddress) => addressBook, +); + +export const userPreferences = createSlice({ + name: "userPreferences", + initialState, + reducers: { + addToAddressBook: (state, action: PayloadAction) => { + state.addressBook = { + ...state.addressBook, + ...action.payload, + }; + }, + deleteFromAddressBook: (state, action: PayloadAction) => { + const { [action.payload]: _, ...newAddressBook } = state.addressBook; + state.addressBook = newAddressBook; + }, + }, + extraReducers: (builder) => { + builder.addCase( + fetchUserPreferences.fulfilled, + (state, action: PayloadAction) => { + state = action.payload; + return state; + }, + ); + builder.addCase( + setAddresses.fulfilled, + (state, action: PayloadAction) => { + state.addresses = action.payload; + return state; + }, + ); + builder.addCase( + setAddressBook.fulfilled, + (state, action: PayloadAction) => { + state.addressBook = action.payload; + return state; + }, + ); + }, +}); + +export const selectAddressBookArray = createSelector( + (state: UserPreferences) => state.addressBook, + (addressBook) => prepopulateField(addressBook), +); + +export const selectLocalWalletAddressArray = createSelector( + (state: UserPreferences) => state.addresses, + (walletAddress) => prepopulateField(walletAddress), +); diff --git a/walletkit/walletkit-ui/store/wallet.ts b/walletkit/walletkit-ui/store/wallet.ts new file mode 100644 index 0000000000..8f6a39d563 --- /dev/null +++ b/walletkit/walletkit-ui/store/wallet.ts @@ -0,0 +1,376 @@ +import { WhaleApiClient } from "@defichain/whale-api-client"; +import { AddressToken } from "@defichain/whale-api-client/dist/api/address"; +import { + AllSwappableTokensResult, + DexPrice, + PoolPairData, +} from "@defichain/whale-api-client/dist/api/poolpairs"; +import { TokenData } from "@defichain/whale-api-client/dist/api/tokens"; +import { + createAsyncThunk, + createSelector, + createSlice, + PayloadAction, +} from "@reduxjs/toolkit"; +import { getPaginatedResponse } from "@waveshq/walletkit-core"; +import BigNumber from "bignumber.js"; + +interface AssociatedToken { + [key: string]: TokenData; +} + +export interface SwappableTokens { + [key: string]: AllSwappableTokensResult; +} + +export interface DexPricesProps { + [symbol: string]: DexPrice; +} + +export enum AddressType { + WalletAddress, + Whitelisted, + OthersButValid, +} + +export interface WalletState { + utxoBalance: string; + tokens: WalletToken[]; + allTokens: AssociatedToken; + poolpairs: DexItem[]; + dexPrices: { [symbol: string]: DexPricesProps }; + swappableTokens: SwappableTokens; + hasFetchedPoolpairData: boolean; + hasFetchedToken: boolean; + hasFetchedSwappableTokens: boolean; +} + +export interface WalletToken extends AddressToken { + avatarSymbol: string; + usdAmount?: BigNumber; +} + +export interface DexItem { + type: "your" | "available"; + data: PoolPairData; +} + +const initialState: WalletState = { + utxoBalance: "0", + tokens: [], + allTokens: {}, + poolpairs: [], + dexPrices: {}, + swappableTokens: {}, + hasFetchedSwappableTokens: false, + hasFetchedPoolpairData: false, + hasFetchedToken: false, +}; + +const tokenDFI: WalletToken = { + id: "0", + symbol: "DFI", + symbolKey: "DFI", + isDAT: true, + isLPS: false, + isLoanToken: false, + amount: "0", + name: "DeFiChain", + displaySymbol: "DFI (Token)", + avatarSymbol: "DFI (Token)", +}; + +const utxoDFI: WalletToken = { + ...tokenDFI, + id: "0_utxo", + displaySymbol: "DFI (UTXO)", + avatarSymbol: "DFI (UTXO)", +}; + +const unifiedDFI: WalletToken = { + ...tokenDFI, + id: "0_unified", + displaySymbol: "DFI", + avatarSymbol: "DFI", +}; + +/** + * Recursively get all tokens based on pagination info from ApiPagedResponse class + */ +const getAllTokens = async (client: WhaleApiClient): Promise => { + const allTokens: TokenData[] = await getPaginatedResponse( + (limit, next) => client.tokens.list(limit, next), + ); + return allTokens.filter((token) => token.isDAT); +}; + +export const setTokenSymbol = (t: AddressToken): WalletToken => { + let { displaySymbol } = t; + let avatarSymbol = t.displaySymbol; + if (t.id === "0") { + t.name = "DeFiChain"; + displaySymbol = "DFI (Token)"; + } + if (t.id === "0_utxo") { + displaySymbol = "DFI (UTXO)"; + } + if (t.isLPS) { + t.name = t.name.replace("Default Defi token", "DeFiChain"); + avatarSymbol = t.symbol; + } + return { + ...t, + displaySymbol, + avatarSymbol, + }; +}; + +const associateTokens = (tokens: TokenData[]): AssociatedToken => { + const result: AssociatedToken = {}; + tokens.forEach((token) => { + if (token.isDAT) { + result[token.displaySymbol] = token; + } + }); + return result; +}; + +export const fetchPoolPairs = createAsyncThunk( + "wallet/fetchPoolPairs", + async ({ + size = 200, + client, + }: { + size?: number; + client: WhaleApiClient; + }): Promise => { + const pairs = await client.poolpairs.list(size); + return pairs.map((data) => ({ + type: "available", + data, + })); + }, +); + +export const fetchDexPrice = createAsyncThunk( + "wallet/fetchDexPrice", + async ({ + client, + denomination, + }: { + size?: number; + client: WhaleApiClient; + denomination: string; + }): Promise<{ dexPrices: DexPricesProps; denomination: string }> => { + const { dexPrices } = await client.poolpairs.listDexPrices(denomination); + return { + dexPrices, + denomination, + }; + }, +); + +export const fetchTokens = createAsyncThunk( + "wallet/fetchTokens", + async ({ + size = 200, + address, + client, + }: { + size?: number; + address: string; + client: WhaleApiClient; + }): Promise<{ + tokens: AddressToken[]; + allTokens: TokenData[]; + utxoBalance: string; + }> => { + const tokens = await client.address.listToken(address, size); + const allTokens = await getAllTokens(client); + const utxoBalance = await client.address.getBalance(address); + return { + tokens, + allTokens, + utxoBalance, + }; + }, +); + +export const fetchSwappableTokens = createAsyncThunk( + "wallet/swappableTokens", + async ({ + client, + fromTokenId, + }: { + client: WhaleApiClient; + fromTokenId: string; + }): Promise => + client.poolpairs.getSwappableTokens(fromTokenId), +); + +export const wallet = createSlice({ + name: "wallet", + initialState, + reducers: { + setHasFetchedToken: (state, action: PayloadAction) => { + state.hasFetchedToken = action.payload; + }, + }, + extraReducers: (builder) => { + builder.addCase( + fetchPoolPairs.fulfilled, + (state, action: PayloadAction) => { + state.hasFetchedPoolpairData = true; + state.poolpairs = action.payload.filter( + ({ data }) => + !data.symbol.includes("/v1") && !data.symbol.includes("BURN2"), + ); // Filter out v1 pairs due to stock split + }, + ); + builder.addCase( + fetchDexPrice.fulfilled, + ( + state, + action: PayloadAction<{ + dexPrices: DexPricesProps; + denomination: string; + }>, + ) => { + state.dexPrices = { + ...state.dexPrices, + [action.payload.denomination]: action.payload.dexPrices, + }; + }, + ); + builder.addCase( + fetchTokens.fulfilled, + ( + state, + action: PayloadAction<{ + tokens: AddressToken[]; + allTokens: TokenData[]; + utxoBalance: string; + }>, + ) => { + state.hasFetchedToken = true; + state.tokens = action.payload.tokens.map(setTokenSymbol); + state.utxoBalance = action.payload.utxoBalance; + state.allTokens = associateTokens( + action.payload.allTokens.filter( + (token) => !token.symbol.includes("/v1"), + ), + ); // Filter out v1 tokens due to stock split + }, + ); + builder.addCase( + fetchSwappableTokens.fulfilled, + (state, action: PayloadAction) => { + state.hasFetchedSwappableTokens = true; + state.swappableTokens = { + ...state.swappableTokens, + ...{ + [action.payload.fromToken.id]: action.payload, + }, + }; + }, + ); + }, +}); + +const rawTokensSelector = createSelector( + (state: WalletState) => state.tokens, + (tokens) => { + const rawTokens: WalletToken[] = []; + if (!tokens.some((t) => t.id === "0_utxo")) { + rawTokens.push(utxoDFI); + } + if (!tokens.some((t) => t.id === "0")) { + rawTokens.push(tokenDFI); + } + if (!tokens.some((t) => t.id === "0_unified")) { + rawTokens.push(unifiedDFI); + } + return [...rawTokens, ...tokens]; + }, +); + +export const tokensSelector = createSelector( + [rawTokensSelector, (state: WalletState) => state.utxoBalance], + (tokens, utxoBalance) => { + const utxoAmount = new BigNumber(utxoBalance); + const tokenAmount = new BigNumber( + (tokens.find((t) => t.id === "0") ?? tokenDFI).amount, + ); + return tokens.map((t) => { + if (t.id === "0_utxo") { + return { + ...t, + amount: utxoAmount.toFixed(8), + }; + } + if (t.id === "0_unified") { + return { + ...t, + amount: utxoAmount.plus(tokenAmount).toFixed(8), + }; + } + return t; + }); + }, +); + +export const DFITokenSelector = createSelector( + tokensSelector, + (tokens) => tokens.find((token) => token.id === "0") ?? tokenDFI, +); + +export const DFIUtxoSelector = createSelector( + tokensSelector, + (tokens) => tokens.find((token) => token.id === "0_utxo") ?? utxoDFI, +); + +export const unifiedDFISelector = createSelector( + tokensSelector, + (tokens) => tokens.find((token) => token.id === "0_unified") ?? unifiedDFI, +); + +const selectTokenId = (state: WalletState, tokenId: string): string => tokenId; + +/** + * Get single token by `id` from wallet store. + * To get DFI Token or DFI UTXO, use `DFITokenSelector` or `DFIUtxoSelector` instead + */ +export const tokenSelector = createSelector( + [tokensSelector, selectTokenId], + (tokens, tokenId) => + tokens.find((token) => { + if (tokenId === "0" || tokenId === "0_utxo") { + return token.id === "0_unified"; + } + return token.id === tokenId; + }), +); + +/** + * Get single token detail by `displaySymbol` from wallet store. + */ +export const tokenSelectorByDisplaySymbol = createSelector( + [(state: WalletState) => state.allTokens, selectTokenId], + (allTokens, displaySymbol) => allTokens[displaySymbol], +); + +/** + * Get dexprices by currency denomination + */ +export const dexPricesSelectorByDenomination = createSelector( + [(state: WalletState) => state.dexPrices, selectTokenId], + (dexPrices, denomination) => dexPrices[denomination] ?? {}, +); + +/** + * Get single poolpair by id + */ +export const poolPairSelector = createSelector( + [(state: WalletState) => state.poolpairs, selectTokenId], + (poolpairs, id) => poolpairs.find((pair) => pair.data.id === id), +); diff --git a/walletkit/walletkit-ui/store/wallet.unit.ts b/walletkit/walletkit-ui/store/wallet.unit.ts new file mode 100644 index 0000000000..4530ba037c --- /dev/null +++ b/walletkit/walletkit-ui/store/wallet.unit.ts @@ -0,0 +1,316 @@ +import { TokenData } from "@defichain/whale-api-client/dist/api/tokens"; + +import { + DexItem, + fetchPoolPairs, + fetchTokens, + tokensSelector, + wallet, + WalletState, + WalletToken, +} from "./wallet"; + +describe("wallet reducer", () => { + let initialState: WalletState; + let tokenDFI: WalletToken; + let utxoDFI: WalletToken; + let unifiedDFI: WalletToken; + let detailedDFI: TokenData; + + const dfi = { + id: "0", + isDAT: true, + isLPS: false, + isLoanToken: false, + name: "DeFiChain", + symbol: "DFI", + symbolKey: "DFI", + displaySymbol: "DFI (Token)", + avatarSymbol: "DFI (Token)", + }; + + beforeEach(() => { + initialState = { + tokens: [], + allTokens: {}, + utxoBalance: "0", + poolpairs: [], + dexPrices: {}, + swappableTokens: {}, + hasFetchedPoolpairData: false, + hasFetchedToken: true, + hasFetchedSwappableTokens: false, + }; + tokenDFI = { + ...dfi, + amount: "100000", + }; + utxoDFI = { + ...tokenDFI, + amount: "0", + id: "0_utxo", + displaySymbol: "DFI (UTXO)", + avatarSymbol: "DFI (UTXO)", + }; + unifiedDFI = { + ...tokenDFI, + amount: "0", + id: "0_unified", + displaySymbol: "DFI", + avatarSymbol: "DFI", + }; + detailedDFI = { + ...dfi, + creation: { + tx: "0000000000000000000000000000000000000000000000000000000000000000", + height: 0, + }, + decimal: 8, + destruction: { + tx: "0000000000000000000000000000000000000000000000000000000000000000", + height: -1, + }, + finalized: true, + limit: "0", + mintable: false, + minted: "0", + tradeable: true, + }; + }); + + it("should handle initial state", () => { + expect(wallet.reducer(undefined, { type: "unknown" })).toEqual({ + utxoBalance: "0", + tokens: [], + allTokens: {}, + poolpairs: [], + dexPrices: {}, + swappableTokens: {}, + hasFetchedPoolpairData: false, + hasFetchedSwappableTokens: false, + hasFetchedToken: false, + }); + }); + + it("should handle setTokens and setUtxoBalance", () => { + const tokens: WalletToken[] = [tokenDFI, utxoDFI]; + const allTokens = { + "DFI (Token)": detailedDFI, + }; + + const utxoBalance = "77"; + const action = { + type: fetchTokens.fulfilled.type, + payload: { tokens, utxoBalance, allTokens: [detailedDFI] }, + }; + const actual = wallet.reducer(initialState, action); + expect(actual.tokens).toStrictEqual(tokens); + expect(actual.utxoBalance).toStrictEqual("77"); + expect(actual.allTokens).toStrictEqual(allTokens); + }); + + it("should filter out v1 tokens", () => { + const allTokens: TokenData[] = [ + { + id: "0", + symbol: "AMZN/v1", + symbolKey: "AMZN/v1", + name: "dAMZN", + decimal: 8, + limit: "0", + mintable: false, + tradeable: false, + isDAT: true, + isLPS: false, + isLoanToken: false, + finalized: true, + minted: "0", + creation: { + tx: "0000000000000000000000000000000000000000000000000000000000000000", + height: 1, + }, + destruction: { + tx: "0000000000000000000000000000000000000000000000000000000000000000", + height: 0, + }, + displaySymbol: "dAMZN/v1", + }, + ]; + const tokens: WalletToken[] = [tokenDFI, utxoDFI]; + const utxoBalance = "77"; + + const action = { + type: fetchTokens.fulfilled.type, + payload: { tokens, utxoBalance, allTokens }, + }; + const actual = wallet.reducer(initialState, action); + expect(Object.keys(actual.allTokens).length).toStrictEqual(0); + }); + + it("should handle setPoolpairs", () => { + const payload: DexItem[] = [ + { + type: "available", + data: { + id: "8", + symbol: "DFI-USDT", + name: "Default Defi token-Playground USDT", + status: true, + displaySymbol: "dUSDT-DFI", + tokenA: { + name: "DeFiChain", + id: "0", + reserve: "1000", + blockCommission: "0", + symbol: "DFI", + displaySymbol: "dDFI", + }, + tokenB: { + name: "Tether", + id: "3", + reserve: "10000000", + blockCommission: "0", + symbol: "USDT", + displaySymbol: "dUSDT", + }, + priceRatio: { + ab: "0.0001", + ba: "10000", + }, + commission: "0", + totalLiquidity: { + token: "100000", + usd: "20000000", + }, + tradeEnabled: true, + ownerAddress: "mswsMVsyGMj1FzDMbbxw2QW3KvQAv2FKiy", + rewardPct: "0.2", + creation: { + tx: "f691c8b0a5d362a013a7207228e618d832c0b99af8da99c847923f5f93136d60", + height: 119, + }, + apr: { + reward: 133.7652, + total: 133.7652, + commission: 0, + }, + rewardLoanPct: "0", + }, + }, + ]; + + const action = { type: fetchPoolPairs.fulfilled.type, payload }; + const actual = wallet.reducer(initialState, action); + expect(actual.poolpairs).toStrictEqual(payload); + }); + + it("should filter out v1 Poolpairs", () => { + const payload: DexItem[] = [ + { + type: "available", + data: { + id: "8", + symbol: "AMZN-DUSD/v1", + name: "dAMZN-Decentralized USD", + status: true, + displaySymbol: "dAMZN-dDUSD/v1", + tokenA: { + id: "0", + reserve: "1000", + blockCommission: "0", + symbol: "AMZN", + displaySymbol: "dAMZN", + name: "dAmazon", + }, + tokenB: { + id: "3", + reserve: "10000000", + blockCommission: "0", + symbol: "DUSD/v1", + displaySymbol: "dDUSD/v1", + name: "Old DUSD", + }, + priceRatio: { + ab: "0.0001", + ba: "10000", + }, + commission: "0", + totalLiquidity: { + token: "100000", + usd: "20000000", + }, + tradeEnabled: true, + ownerAddress: "mswsMVsyGMj1FzDMbbxw2QW3KvQAv2FKiy", + rewardPct: "0.2", + creation: { + tx: "f691c8b0a5d362a013a7207228e618d832c0b99af8da99c847923f5f93136d60", + height: 119, + }, + apr: { + reward: 133.7652, + total: 133.7652, + commission: 0, + }, + rewardLoanPct: "0", + }, + }, + ]; + const action = { type: fetchPoolPairs.fulfilled.type, payload }; + const actual = wallet.reducer(initialState, action); + expect(actual.poolpairs.length).toStrictEqual(0); + }); + + it("should able to select tokens with default DFIs", () => { + const actual = tokensSelector({ + ...initialState, + utxoBalance: "77", + }); + expect(actual).toStrictEqual([ + { + ...utxoDFI, + amount: "77.00000000", + }, + { + ...tokenDFI, + amount: "0", + }, + { + ...unifiedDFI, + amount: "77.00000000", + }, + ]); + }); + + it("should able to select tokens with existing DFI Token", () => { + const btc = { + id: "1", + isLPS: false, + name: "Bitcoin", + isDAT: true, + symbol: "BTC", + symbolKey: "BTC", + amount: "1", + displaySymbol: "BTC", + avatarSymbol: "BTC", + isLoanToken: false, + }; + const state = { + ...initialState, + utxoBalance: "77.00000000", + tokens: [{ ...utxoDFI }, { ...tokenDFI }, { ...unifiedDFI }, { ...btc }], + }; + const actual = tokensSelector(state); + expect(actual).toStrictEqual([ + { + ...utxoDFI, + amount: "77.00000000", + }, + { ...tokenDFI }, + { + ...unifiedDFI, + amount: "100077.00000000", + }, + { ...btc }, + ]); + }); +}); diff --git a/walletkit/walletkit-ui/store/website.ts b/walletkit/walletkit-ui/store/website.ts new file mode 100644 index 0000000000..0295106eed --- /dev/null +++ b/walletkit/walletkit-ui/store/website.ts @@ -0,0 +1,86 @@ +import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react"; +import { + AnnouncementData, + DeFiChainStatus, + FeatureFlag, + PoolpairWithStabInfo, +} from "@waveshq/walletkit-core"; + +export const statusWebsiteSlice = createApi({ + reducerPath: "websiteStatus", + baseQuery: fetchBaseQuery({ + baseUrl: "https://api.status.jellyfishsdk.com", + }), + endpoints: (builder) => ({ + getBlockchainStatus: builder.query({ + query: () => ({ + url: "/blockchain", + method: "GET", + }), + }), + // Ocean API + getOceanStatus: builder.query({ + query: () => ({ + url: "/overall", + method: "GET", + }), + }), + }), +}); + +export const announcementWebsiteSlice = createApi({ + reducerPath: "website", + baseQuery: fetchBaseQuery({ + baseUrl: "https://wallet.defichain.com/api/v0", + }), + endpoints: (builder) => ({ + getAnnouncements: builder.query({ + query: () => ({ + url: "/announcements", + method: "GET", + headers: { + "Access-Control-Allow-Origin": "*", + mode: "no-cors", + }, + }), + }), + getFeatureFlags: builder.query({ + query: () => ({ + url: "/settings/flags", + method: "GET", + headers: { + "Access-Control-Allow-Origin": "*", + mode: "no-cors", + }, + }), + }), + getPairsWithStabilizationFee: builder.query({ + query: (reqParams) => ({ + url: "/wallet/pairs-with-stab-info", + params: reqParams, + method: "GET", + headers: { + "Access-Control-Allow-Origin": "*", + mode: "no-cors", + }, + }), + }), + }), +}); + +const { useGetBlockchainStatusQuery, useGetOceanStatusQuery } = + statusWebsiteSlice; +const { + useGetAnnouncementsQuery, + useGetFeatureFlagsQuery, + usePrefetch, + useGetPairsWithStabilizationFeeQuery, +} = announcementWebsiteSlice; +export { + useGetAnnouncementsQuery, + useGetBlockchainStatusQuery, + useGetFeatureFlagsQuery, + useGetOceanStatusQuery, + useGetPairsWithStabilizationFeeQuery, + usePrefetch, +};