diff --git a/.eslintrc b/.eslintrc
index 91203fc36..611847f39 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -4,7 +4,7 @@
"project": "./tsconfig.json",
"parser": "@typescript-eslint/parser"
},
- "plugins": ["@typescript-eslint"],
+ "plugins": ["@typescript-eslint", "unused-imports"],
"extends": [
"react-app",
"react-app/jest",
@@ -21,7 +21,8 @@
"jest/no-identical-title": "warn",
"jest/valid-expect": "warn",
"@typescript-eslint/await-thenable": "warn",
- "@typescript-eslint/no-unnecessary-condition": "warn"
+ "@typescript-eslint/no-unnecessary-condition": "warn",
+ "unused-imports/no-unused-imports": "warn"
},
"overrides": [
{
diff --git a/package.json b/package.json
index 525be15b8..c0ba77745 100644
--- a/package.json
+++ b/package.json
@@ -102,6 +102,7 @@
"electronmon": "^2.0.2",
"eslint": "^8.47.0",
"eslint-plugin-storybook": "^0.6.13",
+ "eslint-plugin-unused-imports": "^3.0.0",
"framer-motion": "^10.15.2",
"graphql": "^16.8.0",
"graphql-request": "^6.1.0",
diff --git a/src/components/AccountCard/AccountCard.test.tsx b/src/components/AccountCard/AccountCard.test.tsx
index 7521d168c..75f4198e1 100644
--- a/src/components/AccountCard/AccountCard.test.tsx
+++ b/src/components/AccountCard/AccountCard.test.tsx
@@ -20,14 +20,10 @@ import { multisigToAccount } from "../../utils/multisig/helpers";
import { Multisig } from "../../utils/multisig/types";
import multisigsSlice, { multisigActions } from "../../utils/redux/slices/multisigsSlice";
import tokensSlice from "../../utils/redux/slices/tokensSlice";
-import { TezosNetwork } from "../../types/TezosNetwork";
-const {
- updateTezBalance,
- updateTokenBalance,
- updateTezTransfers,
- updateNetwork,
- updateDelegations,
-} = assetsSlice.actions;
+import { GHOSTNET, MAINNET } from "../../types/Network";
+import { networksActions } from "../../utils/redux/slices/networks";
+const { updateTezBalance, updateTokenBalance, updateTezTransfers, updateDelegations } =
+ assetsSlice.actions;
const { addAccount } = accountsSlice.actions;
const { setMultisigs } = multisigsSlice.actions;
@@ -39,7 +35,7 @@ const mockNft = mockNFTToken(0, pkh);
const SELECTED_ACCOUNT_BALANCE = 33200000000;
beforeEach(() => {
- store.dispatch(assetsSlice.actions.updateNetwork(TezosNetwork.MAINNET));
+ store.dispatch(networksActions.setCurrent(MAINNET));
store.dispatch(setMultisigs(multisigs));
store.dispatch(addAccount([selectedAccount, mockImplicitAccount(1)]));
store.dispatch(updateTezBalance([{ address: pkh, balance: SELECTED_ACCOUNT_BALANCE }]));
@@ -54,7 +50,7 @@ beforeEach(() => {
);
store.dispatch(
tokensSlice.actions.addTokens({
- network: TezosNetwork.MAINNET,
+ network: MAINNET,
tokens: [
hedgehoge(selectedAccount.address).token,
tzBtsc(selectedAccount.address).token,
@@ -90,7 +86,7 @@ describe("", () => {
expect(link).toHaveProperty("href", expectedLink);
{
- act(() => store.dispatch(updateNetwork(TezosNetwork.GHOSTNET)));
+ act(() => store.dispatch(networksActions.setCurrent(GHOSTNET)));
const tzktLink = screen.getByTestId("asset-panel-tablist");
const link = within(tzktLink).getByRole("link", {});
diff --git a/src/components/AccountCard/AccountCardDisplay.tsx b/src/components/AccountCard/AccountCardDisplay.tsx
index ace20766e..874ade01a 100644
--- a/src/components/AccountCard/AccountCardDisplay.tsx
+++ b/src/components/AccountCard/AccountCardDisplay.tsx
@@ -12,7 +12,7 @@ import { AssetsPanel } from "./AssetsPanel/AssetsPanel";
import MultisigApprovers from "./MultisigApprovers";
import AddressPill from "../AddressPill/AddressPill";
import { OperationDisplay } from "../../types/Transfer";
-import { TezosNetwork } from "../../types/TezosNetwork";
+import { Network } from "../../types/Network";
import { DynamicModalContext } from "../DynamicModal";
import { useContext } from "react";
import DelegationFormPage from "../SendFlow/Delegation/FormPage";
@@ -31,7 +31,7 @@ type Props = {
nfts: Array;
operationDisplays: Array;
account: Account;
- network: TezosNetwork;
+ network: Network;
};
const RoundButton: React.FC<{
diff --git a/src/components/AccountCard/AssetsPanel/AssetPanel.test.tsx b/src/components/AccountCard/AssetsPanel/AssetPanel.test.tsx
index 1de43585f..9dfe1ca4d 100644
--- a/src/components/AccountCard/AssetsPanel/AssetPanel.test.tsx
+++ b/src/components/AccountCard/AssetsPanel/AssetPanel.test.tsx
@@ -1,6 +1,6 @@
import { mockMultisigAccount } from "../../../mocks/factories";
import { render, screen } from "../../../mocks/testUtils";
-import { TezosNetwork } from "../../../types/TezosNetwork";
+import { MAINNET } from "../../../types/Network";
import { AssetsPanel } from "./AssetsPanel";
describe("", () => {
@@ -12,7 +12,7 @@ describe("", () => {
nfts={[]}
tokens={[]}
operationDisplays={[]}
- network={TezosNetwork.MAINNET}
+ network={MAINNET}
/>
);
diff --git a/src/components/AccountCard/AssetsPanel/AssetsPanel.tsx b/src/components/AccountCard/AssetsPanel/AssetsPanel.tsx
index d5a9926ae..a215c5f67 100644
--- a/src/components/AccountCard/AssetsPanel/AssetsPanel.tsx
+++ b/src/components/AccountCard/AssetsPanel/AssetsPanel.tsx
@@ -13,7 +13,7 @@ import { DelegationDisplay } from "./DelegationDisplay";
import MultisigPendingAccordion from "./MultisigPendingAccordion";
import { NFTsGrid } from "./NFTsGrid";
import { TokenList } from "./TokenList";
-import { TezosNetwork } from "../../../types/TezosNetwork";
+import { Network } from "../../../types/Network";
import { useAllDelegations } from "../../../utils/hooks/assetsHooks";
export const AssetsPanel: React.FC<{
@@ -21,7 +21,7 @@ export const AssetsPanel: React.FC<{
nfts: Array;
account: Account;
operationDisplays: OperationDisplay[];
- network: TezosNetwork;
+ network: Network;
}> = ({ tokens, nfts, account, operationDisplays, network }) => {
const isMultisig = account.type === AccountType.MULTISIG;
const rawDelegations = useAllDelegations()[account.address.pkh];
diff --git a/src/components/AccountCard/AssetsPanel/MultisigPendingAccordion/MultisigDecodedOperationItem.test.tsx b/src/components/AccountCard/AssetsPanel/MultisigPendingAccordion/MultisigDecodedOperationItem.test.tsx
index f693bc43d..5c19bcdda 100644
--- a/src/components/AccountCard/AssetsPanel/MultisigPendingAccordion/MultisigDecodedOperationItem.test.tsx
+++ b/src/components/AccountCard/AssetsPanel/MultisigPendingAccordion/MultisigDecodedOperationItem.test.tsx
@@ -1,16 +1,17 @@
import { mockContractAddress, mockImplicitAddress } from "../../../../mocks/factories";
import { render, screen } from "../../../../mocks/testUtils";
-import { TezosNetwork } from "../../../../types/TezosNetwork";
import { RawTokenBalance } from "../../../../types/TokenBalance";
import { assetsActions } from "../../../../utils/redux/slices/assetsSlice";
import store from "../../../../utils/redux/store";
import tokensSlice from "../../../../utils/redux/slices/tokensSlice";
import MultisigDecodedOperationItem from "./MultisigDecodedOperationItem";
+import { MAINNET } from "../../../../types/Network";
+import { networksActions } from "../../../../utils/redux/slices/networks";
-const { updateTokenBalance, updateNetwork } = assetsActions;
+const { updateTokenBalance } = assetsActions;
beforeEach(() => {
- store.dispatch(updateNetwork(TezosNetwork.MAINNET));
+ store.dispatch(networksActions.setCurrent(MAINNET));
});
describe("", () => {
@@ -71,7 +72,7 @@ describe("", () => {
store.dispatch(updateTokenBalance([mockBalancePlayload]));
store.dispatch(
tokensSlice.actions.addTokens({
- network: TezosNetwork.MAINNET,
+ network: MAINNET,
tokens: [mockBalancePlayload.token],
})
);
@@ -119,7 +120,7 @@ describe("", () => {
store.dispatch(updateTokenBalance([mockBalancePlayload]));
store.dispatch(
tokensSlice.actions.addTokens({
- network: TezosNetwork.MAINNET,
+ network: MAINNET,
tokens: [mockBalancePlayload.token],
})
);
diff --git a/src/components/AccountCard/AssetsPanel/MultisigPendingAccordion/MultisigPendingAccordionItem.test.tsx b/src/components/AccountCard/AssetsPanel/MultisigPendingAccordion/MultisigPendingAccordionItem.test.tsx
index 759078b13..d970d8532 100644
--- a/src/components/AccountCard/AssetsPanel/MultisigPendingAccordion/MultisigPendingAccordionItem.test.tsx
+++ b/src/components/AccountCard/AssetsPanel/MultisigPendingAccordion/MultisigPendingAccordionItem.test.tsx
@@ -20,6 +20,7 @@ import { estimate, executeOperations, makeToolkit } from "../../../../utils/tezo
import BigNumber from "bignumber.js";
import { makeAccountOperations } from "../../../sendForm/types";
import { makeMultisigApproveOrExecuteOperation } from "../../../../types/Operation";
+import { MAINNET } from "../../../../types/Network";
jest.mock("../../../../utils/hooks/accountUtils");
jest.mock("../../../sendForm/types");
@@ -102,7 +103,7 @@ describe("", () => {
makeMultisigApproveOrExecuteOperation(multisig.address, "execute", pendingOps[0].id),
]);
- expect(jest.mocked(estimate)).toHaveBeenCalledWith(operation, "mainnet");
+ expect(jest.mocked(estimate)).toHaveBeenCalledWith(operation, MAINNET);
fillPassword("mockPass");
@@ -150,7 +151,7 @@ describe("", () => {
makeMultisigApproveOrExecuteOperation(multisig.address, "approve", pendingOps[0].id),
]);
- expect(jest.mocked(estimate)).toHaveBeenCalledWith(operations, "mainnet");
+ expect(jest.mocked(estimate)).toHaveBeenCalledWith(operations, MAINNET);
fillPassword("mockPass");
diff --git a/src/components/AccountCard/AssetsPanel/MultisigPendingAccordion/MultisigSignerTile.tsx b/src/components/AccountCard/AssetsPanel/MultisigPendingAccordion/MultisigSignerTile.tsx
index 9f5abf90a..aa3841583 100644
--- a/src/components/AccountCard/AssetsPanel/MultisigPendingAccordion/MultisigSignerTile.tsx
+++ b/src/components/AccountCard/AssetsPanel/MultisigPendingAccordion/MultisigSignerTile.tsx
@@ -2,7 +2,6 @@ import React, { useContext } from "react";
import { ImplicitAccount, MultisigAccount } from "../../../../types/Account";
import { ImplicitAddress } from "../../../../types/Address";
import { useGetImplicitAccountSafe } from "../../../../utils/hooks/accountHooks";
-import { useSelectedNetwork } from "../../../../utils/hooks/assetsHooks";
import { useGetContactName } from "../../../../utils/hooks/contactsHooks";
import { useAsyncActionHandler } from "../../../../utils/hooks/useAsyncActionHandler";
import { MultisigOperation } from "../../../../utils/multisig/types";
@@ -13,6 +12,7 @@ import { estimate } from "../../../../utils/tezos";
import { DynamicModalContext } from "../../../DynamicModal";
import SignPage from "../../../SendFlow/Multisig/SignPage";
import { MultisigSignerTileDisplay } from "./MultisigSignerTileDisplay";
+import { useSelectedNetwork } from "../../../../utils/hooks/networkHooks";
const MultisigSignerTile: React.FC<{
signerAddress: ImplicitAddress;
diff --git a/src/components/AccountCard/index.tsx b/src/components/AccountCard/index.tsx
index 03d17a1c5..d49af7a1f 100644
--- a/src/components/AccountCard/index.tsx
+++ b/src/components/AccountCard/index.tsx
@@ -6,12 +6,12 @@ import {
useGetAccountNFTs,
useGetAccountOperationDisplays,
useGetDollarBalance,
- useSelectedNetwork,
} from "../../utils/hooks/assetsHooks";
import { DynamicModalContext } from "../DynamicModal";
import { useReceiveModal } from "../ReceiveModal";
import SendTezForm from "../SendFlow/Tez/FormPage";
import { AccountCardDisplay } from "./AccountCardDisplay";
+import { useSelectedNetwork } from "../../utils/hooks/networkHooks";
export const AccountCard: React.FC<{ account: Account }> = ({ account }) => {
const accountBalance = useGetAccountBalance();
diff --git a/src/components/AddressPill/AddressPill.test.tsx b/src/components/AddressPill/AddressPill.test.tsx
index c5afd9270..ae6e9fbcd 100644
--- a/src/components/AddressPill/AddressPill.test.tsx
+++ b/src/components/AddressPill/AddressPill.test.tsx
@@ -2,14 +2,13 @@ import { contact1 } from "../../mocks/contacts";
import { mockFA1TokenRaw, mockImplicitAddress } from "../../mocks/factories";
import { render, screen } from "../../mocks/testUtils";
import { parseContractPkh, parseImplicitPkh } from "../../types/Address";
-import { TezosNetwork } from "../../types/TezosNetwork";
-import assetsSlice from "../../utils/redux/slices/assetsSlice";
import { contactsActions } from "../../utils/redux/slices/contactsSlice";
import store from "../../utils/redux/store";
import tokensSlice from "../../utils/redux/slices/tokensSlice";
import AddressPill from "./AddressPill";
+import { MAINNET } from "../../types/Network";
+import { networksActions } from "../../utils/redux/slices/networks";
const { upsert } = contactsActions;
-const { updateNetwork } = assetsSlice.actions;
describe("", () => {
it("displays left icon", () => {
@@ -42,10 +41,8 @@ describe("", () => {
it("is removable for two icons", () => {
const address = mockImplicitAddress(0);
const fa1 = mockFA1TokenRaw(1, address.pkh, 123);
- store.dispatch(updateNetwork(TezosNetwork.MAINNET));
- store.dispatch(
- tokensSlice.actions.addTokens({ network: TezosNetwork.MAINNET, tokens: [fa1.token] })
- );
+ store.dispatch(networksActions.setCurrent(MAINNET));
+ store.dispatch(tokensSlice.actions.addTokens({ network: MAINNET, tokens: [fa1.token] }));
render(
{
- store.dispatch(assetsSlice.actions.updateNetwork(TezosNetwork.MAINNET));
+ store.dispatch(networksActions.setCurrent(MAINNET));
});
describe("useAddressKind", () => {
@@ -58,7 +59,7 @@ describe("useAddressKind", () => {
delete withoutName.token.metadata?.name;
store.dispatch(
tokensSlice.actions.addTokens({
- network: TezosNetwork.MAINNET,
+ network: MAINNET,
tokens: [withoutName.token],
})
);
@@ -76,7 +77,7 @@ describe("useAddressKind", () => {
it("returns label", () => {
store.dispatch(
tokensSlice.actions.addTokens({
- network: TezosNetwork.MAINNET,
+ network: MAINNET,
tokens: [tokenBalance.token],
})
);
@@ -140,7 +141,7 @@ describe("useAddressKind", () => {
store.dispatch(accountsSlice.actions.addAccount([mockImplicitAccount(0)]));
store.dispatch(
tokensSlice.actions.addTokens({
- network: TezosNetwork.MAINNET,
+ network: MAINNET,
tokens: [hedgehoge(mockImplicitAddress(0)).token, uUSD(mockImplicitAddress(0)).token],
})
);
diff --git a/src/components/AddressPill/useAddressKind.ts b/src/components/AddressPill/useAddressKind.ts
index 8bbb410d3..432bdce2b 100644
--- a/src/components/AddressPill/useAddressKind.ts
+++ b/src/components/AddressPill/useAddressKind.ts
@@ -2,7 +2,7 @@ import { Address } from "../../types/Address";
import { useGetContactName } from "../../utils/hooks/contactsHooks";
import { useGetOwnedAccountSafe } from "../../utils/hooks/accountHooks";
import { AccountType } from "../../types/Account";
-import { useGetBaker, useSelectedNetwork } from "../../utils/hooks/assetsHooks";
+import { useGetBaker } from "../../utils/hooks/assetsHooks";
import {
AddressKind,
BakerAddress,
@@ -13,6 +13,7 @@ import {
OwnedMultisigAccountAddress,
} from "./types";
import { useGetTokenType } from "../../utils/hooks/tokensHooks";
+import { useSelectedNetwork } from "../../utils/hooks/networkHooks";
const useAddressKind = (address: Address): AddressKind => {
const ownedAccount = useOwnedAccountAddressKind(address);
diff --git a/src/components/BuyTez/BuyTezForm.test.tsx b/src/components/BuyTez/BuyTezForm.test.tsx
index a389aad5a..0842bcb2d 100644
--- a/src/components/BuyTez/BuyTezForm.test.tsx
+++ b/src/components/BuyTez/BuyTezForm.test.tsx
@@ -1,9 +1,9 @@
import { Modal } from "@chakra-ui/react";
import { render, screen } from "../../mocks/testUtils";
-import { TezosNetwork } from "../../types/TezosNetwork";
-import { assetsActions } from "../../utils/redux/slices/assetsSlice";
import store from "../../utils/redux/store";
import BuyTezForm from "./BuyTezForm";
+import { GHOSTNET, MAINNET } from "../../types/Network";
+import { networksActions } from "../../utils/redux/slices/networks";
const fixture = () => (
{}}>
@@ -13,7 +13,7 @@ const fixture = () => (
describe("", () => {
test("renders request Tez from faucet on ghostnet", async () => {
- store.dispatch(assetsActions.updateNetwork(TezosNetwork.GHOSTNET));
+ store.dispatch(networksActions.setCurrent(GHOSTNET));
render(fixture());
// Async findBy because otherwise we get act warning since store.dispatch is async
@@ -22,11 +22,11 @@ describe("", () => {
});
test("renders Buy Tez from faucet on ghostnet", async () => {
- store.dispatch(assetsActions.updateNetwork(TezosNetwork.MAINNET));
+ store.dispatch(networksActions.setCurrent(MAINNET));
render(fixture());
const result = await screen.findByTestId("buy-tez-button");
expect(result).toHaveTextContent("Buy Tez");
- expect(screen.getByTestId("buy-tez-selector")).toBeTruthy();
+ expect(screen.getByTestId("buy-tez-selector")).toBeInTheDocument();
});
});
diff --git a/src/components/BuyTez/BuyTezForm.tsx b/src/components/BuyTez/BuyTezForm.tsx
index cc9b069f4..7f77fd620 100644
--- a/src/components/BuyTez/BuyTezForm.tsx
+++ b/src/components/BuyTez/BuyTezForm.tsx
@@ -9,20 +9,21 @@ import {
Button,
} from "@chakra-ui/react";
import { FormProvider, useForm } from "react-hook-form";
-import { TezosNetwork } from "../../types/TezosNetwork";
import { navigateToExternalLink } from "../../utils/helpers";
-import { useSelectedNetwork } from "../../utils/hooks/assetsHooks";
-import { wertUrls } from "../../utils/tezos/consts";
import { OwnedImplicitAccountsAutocomplete } from "../AddressAutocomplete";
import { FormErrorMessage } from "../FormErrorMessage";
+import { useSelectedNetwork } from "../../utils/hooks/networkHooks";
const BuyTezForm = () => {
const network = useSelectedNetwork();
- const isMainnet = network === TezosNetwork.MAINNET;
+ const isMainnet = network.name === "mainnet";
const title = isMainnet ? "Buy Tez" : "Request Tez from faucet";
const onSubmit = async ({ recipient }: { recipient: string }) => {
- let url = wertUrls[network];
+ let url = network.buyTezUrl;
+ if (!url) {
+ throw new Error(`${network.name} does not have a buyTezUrl defined`);
+ }
if (isMainnet) {
url += `/default/widget/?commodity=XTZ%3ATezos&address=${recipient}`;
}
diff --git a/src/components/CSVFileUploader/CSVFileUploadForm.tsx b/src/components/CSVFileUploader/CSVFileUploadForm.tsx
index 355cba894..52f815c27 100644
--- a/src/components/CSVFileUploader/CSVFileUploadForm.tsx
+++ b/src/components/CSVFileUploader/CSVFileUploadForm.tsx
@@ -18,7 +18,6 @@ import { FormProvider, useForm } from "react-hook-form";
import { Operation } from "../../types/Operation";
import { RawPkh } from "../../types/Address";
import { useGetBestSignerForAccount, useGetOwnedAccount } from "../../utils/hooks/accountHooks";
-import { useSelectedNetwork } from "../../utils/hooks/assetsHooks";
import { useGetToken } from "../../utils/hooks/tokensHooks";
import { useAppDispatch } from "../../utils/redux/hooks";
import { estimateAndUpdateBatch } from "../../utils/redux/thunks/estimateAndUpdateBatch";
@@ -29,6 +28,7 @@ import { useAsyncActionHandler } from "../../utils/hooks/useAsyncActionHandler";
import { FormErrorMessage } from "../FormErrorMessage";
import { useContext } from "react";
import { DynamicModalContext } from "../DynamicModal";
+import { useSelectedNetwork } from "../../utils/hooks/networkHooks";
type FormFields = {
sender: RawPkh;
diff --git a/src/components/NetworkSelector.test.tsx b/src/components/NetworkSelector.test.tsx
new file mode 100644
index 000000000..13142f2d3
--- /dev/null
+++ b/src/components/NetworkSelector.test.tsx
@@ -0,0 +1,22 @@
+import { fireEvent, render, screen } from "../mocks/testUtils";
+import { GHOSTNET } from "../types/Network";
+import store from "../utils/redux/store";
+import NetworkSelector from "./NetworkSelector";
+
+describe("", () => {
+ it("shows the current network", () => {
+ render();
+
+ expect(screen.getByTestId("network-selector")).toHaveValue("mainnet");
+ });
+
+ it("changes the selected network globally", () => {
+ render();
+
+ fireEvent.change(screen.getByTestId("network-selector"), { target: { value: "ghostnet" } });
+
+ expect(screen.getByTestId("network-selector")).toHaveValue("ghostnet");
+
+ expect(store.getState().networks.current).toEqual(GHOSTNET);
+ });
+});
diff --git a/src/components/NetworkSelector.tsx b/src/components/NetworkSelector.tsx
new file mode 100644
index 000000000..b8b926b60
--- /dev/null
+++ b/src/components/NetworkSelector.tsx
@@ -0,0 +1,39 @@
+import { Box, Select } from "@chakra-ui/react";
+import { Network, NetworkName } from "../types/Network";
+import { useAvailableNetworks, useSelectedNetwork } from "../utils/hooks/networkHooks";
+import { useAppDispatch } from "../utils/redux/hooks";
+import { networksActions } from "../utils/redux/slices/networks";
+import { capitalize } from "lodash";
+import colors from "../style/colors";
+
+export const NetworkSelector = () => {
+ const currentNetwork = useSelectedNetwork();
+ const availableNetworks = useAvailableNetworks();
+ const dispatch = useAppDispatch();
+
+ const changeNetwork = (name: NetworkName) => {
+ const network = availableNetworks.find(network => network.name === name) as Network;
+ dispatch(networksActions.setCurrent(network));
+ };
+
+ return (
+
+
+
+ );
+};
+
+export default NetworkSelector;
diff --git a/src/components/NetworkSelector/NetworkSelectorDisplay.tsx b/src/components/NetworkSelector/NetworkSelectorDisplay.tsx
deleted file mode 100644
index 80e459330..000000000
--- a/src/components/NetworkSelector/NetworkSelectorDisplay.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import { Box, Select } from "@chakra-ui/react";
-import React from "react";
-import { TezosNetwork } from "../../types/TezosNetwork";
-
-export const NetworkSelectorDisplay: React.FC<{
- value: TezosNetwork;
- onChange: (val: TezosNetwork) => void;
-}> = ({ value, onChange }) => {
- return (
-
-
-
- );
-};
diff --git a/src/components/NetworkSelector/index.tsx b/src/components/NetworkSelector/index.tsx
deleted file mode 100644
index 3d058a88b..000000000
--- a/src/components/NetworkSelector/index.tsx
+++ /dev/null
@@ -1,18 +0,0 @@
-import { TezosNetwork } from "../../types/TezosNetwork";
-import { useSelectedNetwork } from "../../utils/hooks/assetsHooks";
-import { useAppDispatch } from "../../utils/redux/hooks";
-import assetsSlice from "../../utils/redux/slices/assetsSlice";
-import { NetworkSelectorDisplay } from "./NetworkSelectorDisplay";
-
-export const NetworkSelector = () => {
- const network = useSelectedNetwork();
- const dispatch = useAppDispatch();
-
- const changeNetwork = (network: TezosNetwork) => {
- dispatch(assetsSlice.actions.updateNetwork(network));
- };
-
- return ;
-};
-
-export default NetworkSelector;
diff --git a/src/components/Onboarding/FakeAccount.tsx b/src/components/Onboarding/FakeAccount.tsx
index e1b336a1d..521feb6e6 100644
--- a/src/components/Onboarding/FakeAccount.tsx
+++ b/src/components/Onboarding/FakeAccount.tsx
@@ -2,11 +2,11 @@
import { Button, FormControl, FormLabel, Input, Text } from "@chakra-ui/react";
import { useForm } from "react-hook-form";
import { RpcClient } from "@taquito/rpc";
-import { nodeUrls } from "../../utils/tezos/consts";
import { SupportedIcons } from "../CircleIcon";
import ModalContentWrapper from "./ModalContentWrapper";
import { useRestoreLedger } from "../../utils/hooks/accountHooks";
import { defaultDerivationPathPattern } from "../../utils/account/derivationPathUtils";
+import { MAINNET } from "../../types/Network";
export const FakeAccount = ({ onClose }: { onClose: () => void }) => {
const {
@@ -17,7 +17,7 @@ export const FakeAccount = ({ onClose }: { onClose: () => void }) => {
const restoreLedger = useRestoreLedger();
const onSubmit = async ({ pkh, name }: { pkh: string; name: string }) => {
- const rpc = new RpcClient(nodeUrls["mainnet"]);
+ const rpc = new RpcClient(MAINNET.rpcUrl);
const managerKey = await rpc.getManagerKey(pkh);
const pk = typeof managerKey === "string" ? managerKey : managerKey.key;
restoreLedger(defaultDerivationPathPattern, pk, pkh, name);
diff --git a/src/components/SendFlow/onSubmitFormActionHooks.tsx b/src/components/SendFlow/onSubmitFormActionHooks.tsx
index 793003ec8..cdb9be901 100644
--- a/src/components/SendFlow/onSubmitFormActionHooks.tsx
+++ b/src/components/SendFlow/onSubmitFormActionHooks.tsx
@@ -1,13 +1,13 @@
import { useContext } from "react";
import { BaseFormValues, FormPageProps, SignPageProps, useMakeFormOperations } from "./utils";
import { DynamicModalContext } from "../DynamicModal";
-import { useSelectedNetwork } from "../../utils/hooks/assetsHooks";
import { Operation } from "../../types/Operation";
import { useAppDispatch } from "../../utils/redux/hooks";
import { useToast } from "@chakra-ui/toast";
import { estimateAndUpdateBatch } from "../../utils/redux/thunks/estimateAndUpdateBatch";
import { useAsyncActionHandler } from "../../utils/hooks/useAsyncActionHandler";
import { estimate } from "../../utils/tezos";
+import { useSelectedNetwork } from "../../utils/hooks/networkHooks";
// This file defines hooks to create actions when form is submitted.
diff --git a/src/components/SendFlow/utils.tsx b/src/components/SendFlow/utils.tsx
index e14457c33..bed729b8c 100644
--- a/src/components/SendFlow/utils.tsx
+++ b/src/components/SendFlow/utils.tsx
@@ -6,7 +6,7 @@ import {
useGetImplicitAccount,
useGetOwnedAccount,
} from "../../utils/hooks/accountHooks";
-import { useClearBatch, useSelectedNetwork } from "../../utils/hooks/assetsHooks";
+import { useClearBatch } from "../../utils/hooks/assetsHooks";
import { DynamicModalContext } from "../DynamicModal";
import { AccountOperations, makeAccountOperations } from "../sendForm/types";
import BigNumber from "bignumber.js";
@@ -18,6 +18,7 @@ import { SuccessStep } from "../sendForm/steps/SuccessStep";
import { estimate, executeOperations } from "../../utils/tezos";
import { useForm } from "react-hook-form";
import { repeat } from "lodash";
+import { useSelectedNetwork } from "../../utils/hooks/networkHooks";
// Convert given optional fields to required
// For example:
diff --git a/src/components/sendForm/SendForm.test.tsx b/src/components/sendForm/SendForm.test.tsx
index ec1507ad7..c3fd6c855 100644
--- a/src/components/sendForm/SendForm.test.tsx
+++ b/src/components/sendForm/SendForm.test.tsx
@@ -35,8 +35,8 @@ import { multisigs } from "../../mocks/multisig";
import { parseContractPkh, parsePkh } from "../../types/Address";
import tokensSlice from "../../utils/redux/slices/tokensSlice";
import { fa1Token, fa2Token, nft } from "../../mocks/tzktResponse";
-import { TezosNetwork } from "../../types/TezosNetwork";
import { estimate, executeOperations, makeToolkit } from "../../utils/tezos";
+import { MAINNET } from "../../types/Network";
// These tests might take long in the CI
jest.setTimeout(10000);
@@ -65,7 +65,7 @@ beforeEach(async () => {
document.getElementById("chakra-toast-portal")?.remove();
store.dispatch(
tokensSlice.actions.addTokens({
- network: TezosNetwork.MAINNET,
+ network: MAINNET,
tokens: [fa1Token.token, fa2Token.token, nft.token],
})
);
@@ -159,7 +159,7 @@ describe("", () => {
sender: mockImplicitAccount(2),
signer: mockImplicitAccount(2),
},
- "mainnet"
+ MAINNET
);
fillPassword("mockPass");
@@ -180,10 +180,7 @@ describe("", () => {
await waitFor(() => {
expect(screen.getByText(/Operation Submitted/i)).toBeInTheDocument();
- expect(screen.getByTestId(/tzkt-link/i)).toHaveProperty(
- "href",
- "https://mainnet.tzkt.io/mockHash"
- );
+ expect(screen.getByTestId(/tzkt-link/i)).toHaveProperty("href", "https://tzkt.io/mockHash");
});
expect(jest.mocked(executeOperations)).toHaveBeenCalledWith(
@@ -272,7 +269,7 @@ describe("", () => {
sender: mockImplicitAccount(2),
signer: mockImplicitAccount(2),
},
- "mainnet"
+ MAINNET
);
fillPassword("mockPass");
@@ -292,10 +289,7 @@ describe("", () => {
await waitFor(() => {
expect(screen.getByText(/Operation Submitted/i)).toBeInTheDocument();
- expect(screen.getByTestId(/tzkt-link/i)).toHaveProperty(
- "href",
- "https://mainnet.tzkt.io/mockHash"
- );
+ expect(screen.getByTestId(/tzkt-link/i)).toHaveProperty("href", "https://tzkt.io/mockHash");
});
expect(jest.mocked(executeOperations)).toHaveBeenCalledWith(
@@ -374,10 +368,7 @@ describe("", () => {
await waitFor(() => {
expect(screen.getByText(/Operation Submitted/i)).toBeInTheDocument();
- expect(screen.getByTestId(/tzkt-link/i)).toHaveProperty(
- "href",
- "https://mainnet.tzkt.io/mockHash"
- );
+ expect(screen.getByTestId(/tzkt-link/i)).toHaveProperty("href", "https://tzkt.io/mockHash");
});
const contractAddress = nft.token.contract.address as string;
@@ -491,10 +482,7 @@ describe("", () => {
await waitFor(() => {
expect(screen.getByText(/Operation Submitted/i)).toBeInTheDocument();
- expect(screen.getByTestId(/tzkt-link/i)).toHaveProperty(
- "href",
- "https://mainnet.tzkt.io/mockHash"
- );
+ expect(screen.getByTestId(/tzkt-link/i)).toHaveProperty("href", "https://tzkt.io/mockHash");
});
});
@@ -539,10 +527,7 @@ describe("", () => {
await waitFor(() => {
expect(screen.getByText(/Operation Submitted/i)).toBeInTheDocument();
- expect(screen.getByTestId(/tzkt-link/i)).toHaveProperty(
- "href",
- "https://mainnet.tzkt.io/mockHash"
- );
+ expect(screen.getByTestId(/tzkt-link/i)).toHaveProperty("href", "https://tzkt.io/mockHash");
});
});
@@ -605,10 +590,7 @@ describe("", () => {
await waitFor(() => {
expect(screen.getByText(/Operation Submitted/i)).toBeInTheDocument();
- expect(screen.getByTestId(/tzkt-link/i)).toHaveProperty(
- "href",
- "https://mainnet.tzkt.io/mockHash"
- );
+ expect(screen.getByTestId(/tzkt-link/i)).toHaveProperty("href", "https://tzkt.io/mockHash");
});
});
});
diff --git a/src/components/sendForm/SendForm.tsx b/src/components/sendForm/SendForm.tsx
index f34f375f9..dc633c4f3 100644
--- a/src/components/sendForm/SendForm.tsx
+++ b/src/components/sendForm/SendForm.tsx
@@ -4,7 +4,7 @@ import { useEffect, useRef, useState } from "react";
import { RawPkh } from "../../types/Address";
import { Operation } from "../../types/Operation";
import { useGetBestSignerForAccount, useGetOwnedAccount } from "../../utils/hooks/accountHooks";
-import { useClearBatch, useSelectedNetwork } from "../../utils/hooks/assetsHooks";
+import { useClearBatch } from "../../utils/hooks/assetsHooks";
import { useAsyncActionHandler } from "../../utils/hooks/useAsyncActionHandler";
import { useAppDispatch } from "../../utils/redux/hooks";
import { assetsActions } from "../../utils/redux/slices/assetsSlice";
@@ -19,6 +19,7 @@ import {
makeAccountOperations,
SendFormMode,
} from "./types";
+import { useSelectedNetwork } from "../../utils/hooks/networkHooks";
export const SendForm = ({
sender,
diff --git a/src/components/sendForm/components/SignButton.tsx b/src/components/sendForm/components/SignButton.tsx
index 52913493b..daa54727e 100644
--- a/src/components/sendForm/components/SignButton.tsx
+++ b/src/components/sendForm/components/SignButton.tsx
@@ -11,10 +11,10 @@ import {
} from "../../../types/Account";
import { useGetSecretKey } from "../../../utils/hooks/accountUtils";
import { useAsyncActionHandler } from "../../../utils/hooks/useAsyncActionHandler";
-import { useSelectedNetwork } from "../../../utils/hooks/assetsHooks";
import { makeToolkit } from "../../../utils/tezos";
import { FormErrorMessage } from "../../FormErrorMessage";
import PasswordInput from "../../PasswordInput";
+import { useSelectedNetwork } from "../../../utils/hooks/networkHooks";
export const SignWithGoogleButton: React.FC<
PropsWithChildren<{
diff --git a/src/components/sendForm/steps/SuccessStep.tsx b/src/components/sendForm/steps/SuccessStep.tsx
index 89266a0a9..8dd8d10e3 100644
--- a/src/components/sendForm/steps/SuccessStep.tsx
+++ b/src/components/sendForm/steps/SuccessStep.tsx
@@ -14,8 +14,8 @@ import { Link } from "react-router-dom";
import React, { useContext } from "react";
import { getHashUrl } from "../../../views/operations/operationsUtils";
import { TzktLink } from "../../TzktLink";
-import { useSelectedNetwork } from "../../../utils/hooks/assetsHooks";
import { DynamicModalContext } from "../../DynamicModal";
+import { useSelectedNetwork } from "../../../utils/hooks/networkHooks";
export const SuccessStep: React.FC<{ hash: string }> = ({ hash }) => {
const network = useSelectedNetwork();
diff --git a/src/mocks/devSignerKeys.ts b/src/mocks/devSignerKeys.ts
index 66a8dfb0c..a3f54e059 100644
--- a/src/mocks/devSignerKeys.ts
+++ b/src/mocks/devSignerKeys.ts
@@ -1,9 +1,9 @@
import { InMemorySigner } from "@taquito/signer";
import { TezosToolkit } from "@taquito/taquito";
-import { TezosNetwork } from "../types/TezosNetwork";
import { getDefaultDerivationPath } from "../utils/account/derivationPathUtils";
import { makeToolkit } from "../utils/tezos";
import { mnemonic1 } from "./mockMnemonic";
+import { GHOSTNET } from "../types/Network";
// make the default signer used in the dev mode.
// e.g. makeDefaultDevSigner(0) is equivalent to the "restored account 0".
@@ -47,6 +47,6 @@ export const makeToolkitFromDefaultDevSeed = async (index: number): Promise {
afterEach(() => {
act(() => {
store.dispatch(accountsSlice.actions.reset());
- store.dispatch(assetsSlice.actions.reset());
store.dispatch(multisigsSlice.actions.reset());
store.dispatch(contactsActions.reset());
store.dispatch(tokensActions.reset());
store.dispatch(errorsSlice.actions.reset());
+ store.dispatch(networksActions.reset());
});
});
diff --git a/src/types/Network.ts b/src/types/Network.ts
new file mode 100644
index 000000000..ce25b9613
--- /dev/null
+++ b/src/types/Network.ts
@@ -0,0 +1,27 @@
+export const MAINNET: Network = {
+ name: "mainnet",
+ rpcUrl: "https://prod.tcinfra.net/rpc/mainnet/",
+ tzktApiUrl: "https://api.mainnet.tzkt.io",
+ tzktExplorerUrl: "https://tzkt.io",
+ buyTezUrl: "https://widget.wert.io",
+};
+
+export const GHOSTNET: Network = {
+ name: "ghostnet",
+ rpcUrl: "https://ghostnet.ecadinfra.com",
+ tzktApiUrl: "https://api.ghostnet.tzkt.io",
+ tzktExplorerUrl: "https://ghostnet.tzkt.io",
+ buyTezUrl: "https://faucet.ghostnet.teztnets.xyz/",
+};
+
+export type NetworkName = string; // must be unique
+
+export type Network = {
+ name: NetworkName;
+ rpcUrl: string;
+ tzktApiUrl: string;
+ tzktExplorerUrl?: string;
+ buyTezUrl?: string;
+};
+
+export const DefaultNetworks: Network[] = [MAINNET, GHOSTNET];
diff --git a/src/types/SignerConfig.ts b/src/types/SignerConfig.ts
index 4ab1a169c..f3eb32d35 100644
--- a/src/types/SignerConfig.ts
+++ b/src/types/SignerConfig.ts
@@ -1,7 +1,7 @@
import { ImplicitAccount, LedgerAccount } from "./Account";
-import { TezosNetwork } from "./TezosNetwork";
+import { Network } from "./Network";
-export type SignerConfig = { network: TezosNetwork } & (
+export type SignerConfig = { network: Network } & (
| { type: "ledger"; account: LedgerAccount }
| { type: "mnemonic"; secretKey: string }
| { type: "social"; secretKey: string }
diff --git a/src/types/TezosNetwork.ts b/src/types/TezosNetwork.ts
deleted file mode 100644
index 188c7ef41..000000000
--- a/src/types/TezosNetwork.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export enum TezosNetwork {
- MAINNET = "mainnet",
- GHOSTNET = "ghostnet",
-}
diff --git a/src/types/Token.test.tsx b/src/types/Token.test.tsx
index 49362f5aa..276d396ae 100644
--- a/src/types/Token.test.tsx
+++ b/src/types/Token.test.tsx
@@ -2,6 +2,7 @@ import { tzBtsc, hedgehoge } from "../mocks/fa12Tokens";
import { uUSD } from "../mocks/fa2Tokens";
import { mockNFT, mockImplicitAddress } from "../mocks/factories";
import { fa1Token, fa2Token, nft } from "../mocks/tzktResponse";
+import { GHOSTNET, MAINNET } from "./Network";
import {
FA12Token,
FA2Token,
@@ -18,7 +19,6 @@ import {
tokenSymbolSafe,
} from "./Token";
import type { Metadata } from "./Token";
-import { TezosNetwork } from "./TezosNetwork";
beforeEach(() => {
jest.spyOn(console, "warn").mockImplementation();
@@ -362,10 +362,10 @@ describe("metadataUri", () => {
it("returns a tzkt link", () => {
const nft = mockNFT(0);
- expect(metadataUri(nft, TezosNetwork.MAINNET)).toEqual(
- "https://mainnet.tzkt.io/KT1QuofAgnsWffHzLA7D78rxytJruGHDe7XG/tokens/mockId0/metadata"
+ expect(metadataUri(nft, MAINNET)).toEqual(
+ "https://tzkt.io/KT1QuofAgnsWffHzLA7D78rxytJruGHDe7XG/tokens/mockId0/metadata"
);
- expect(metadataUri(nft, TezosNetwork.GHOSTNET)).toEqual(
+ expect(metadataUri(nft, GHOSTNET)).toEqual(
"https://ghostnet.tzkt.io/KT1QuofAgnsWffHzLA7D78rxytJruGHDe7XG/tokens/mockId0/metadata"
);
});
diff --git a/src/types/Token.ts b/src/types/Token.ts
index ba243648d..3f38866d6 100644
--- a/src/types/Token.ts
+++ b/src/types/Token.ts
@@ -3,7 +3,7 @@ import { z } from "zod";
import { Schema as AddressSchema } from "./Address";
import BigNumber from "bignumber.js";
import { getIPFSurl } from "../utils/token/nftUtils";
-import { TezosNetwork } from "./TezosNetwork";
+import { Network } from "./Network";
// TzKT defines metadada as any, but we need to have at least some clarity of what can be inside
export type Metadata = {
@@ -266,12 +266,12 @@ export const royalties = (nft: NFT): Array<{ address: string; share: number }> =
return shares;
};
-export const metadataUri = ({ contract, tokenId }: Token, network: TezosNetwork) => {
- return `https://${network}.tzkt.io/${contract}/tokens/${tokenId}/metadata`;
+export const metadataUri = (token: Token, network: Network) => {
+ return `${tokenUri(token, network)}/metadata`;
};
-export const tokenUri = ({ contract, tokenId }: Token, network: TezosNetwork) => {
- return `https://${network}.tzkt.io/${contract}/tokens/${tokenId}`;
+export const tokenUri = ({ contract, tokenId }: Token, network: Network) => {
+ return `${network.tzktExplorerUrl}/${contract}/tokens/${tokenId}`;
};
export const DEFAULT_FA1_NAME = "FA1.2 token";
diff --git a/src/utils/beacon/BeaconNotification/BeaconRequestNotification.test.tsx b/src/utils/beacon/BeaconNotification/BeaconRequestNotification.test.tsx
index 343f0b0ef..28891f586 100644
--- a/src/utils/beacon/BeaconNotification/BeaconRequestNotification.test.tsx
+++ b/src/utils/beacon/BeaconNotification/BeaconRequestNotification.test.tsx
@@ -217,7 +217,7 @@ describe("", () => {
await waitFor(() => {
expect(screen.getByText(/Operation Submitted/i)).toBeInTheDocument();
});
- expect(screen.getByTestId(/tzkt-link/i)).toHaveProperty("href", "https://mainnet.tzkt.io/bar");
+ expect(screen.getByTestId(/tzkt-link/i)).toHaveProperty("href", "https://tzkt.io/bar");
expect(walletClient.respond).toHaveBeenCalledWith({
id: objectOperationBatchRequest.id,
diff --git a/src/utils/hooks/assetsHooks.ts b/src/utils/hooks/assetsHooks.ts
index 69bcb0b88..54a25cbd4 100644
--- a/src/utils/hooks/assetsHooks.ts
+++ b/src/utils/hooks/assetsHooks.ts
@@ -21,10 +21,7 @@ import { RawPkh } from "../../types/Address";
import assetsSlice from "../redux/slices/assetsSlice";
import { Account } from "../../types/Account";
import { Delegate } from "../../types/Delegate";
-
-export const useSelectedNetwork = () => {
- return useAppSelector(s => s.assets.network);
-};
+import { useSelectedNetwork } from "./networkHooks";
export const useBlockLevel = () => useAppSelector(s => s.assets.blockLevel);
diff --git a/src/utils/hooks/networkHooks.ts b/src/utils/hooks/networkHooks.ts
new file mode 100644
index 000000000..9b9920a28
--- /dev/null
+++ b/src/utils/hooks/networkHooks.ts
@@ -0,0 +1,9 @@
+import { useAppSelector } from "../redux/hooks";
+
+export const useSelectedNetwork = () => {
+ return useAppSelector(s => s.networks.current);
+};
+
+export const useAvailableNetworks = () => {
+ return useAppSelector(s => s.networks.available);
+};
diff --git a/src/utils/hooks/tokensHooks.test.ts b/src/utils/hooks/tokensHooks.test.ts
index dbff33d6c..9bb2a72ee 100644
--- a/src/utils/hooks/tokensHooks.test.ts
+++ b/src/utils/hooks/tokensHooks.test.ts
@@ -3,16 +3,16 @@ import { hedgehoge } from "../../mocks/fa12Tokens";
import { mockContractAddress, mockImplicitAddress } from "../../mocks/factories";
import { ReduxStore } from "../../providers/ReduxStore";
import { fromRaw } from "../../types/Token";
-import { SupportedNetworks } from "../network";
-import { assetsActions } from "../redux/slices/assetsSlice";
import store from "../redux/store";
import { tokensActions } from "../redux/slices/tokensSlice";
import { useGetToken, useGetTokenType } from "./tokensHooks";
+import { DefaultNetworks } from "../../types/Network";
+import { networksActions } from "../redux/slices/networks";
describe("useGetToken", () => {
- describe.each(SupportedNetworks)("on %s", network => {
+ describe.each(DefaultNetworks)("on $name", network => {
beforeEach(() => {
- store.dispatch(assetsActions.updateNetwork(network));
+ store.dispatch(networksActions.setCurrent(network));
});
it("returns undefined if token is not found", () => {
const { result: getTokenRef } = renderHook(() => useGetToken(), {
@@ -32,12 +32,12 @@ describe("useGetToken", () => {
);
});
- SupportedNetworks.forEach(anotherNetwork => {
+ DefaultNetworks.forEach(anotherNetwork => {
if (anotherNetwork === network) {
return;
}
- test.each(SupportedNetworks.filter(another => another !== network))(
+ test.each(DefaultNetworks.filter(another => another !== network))(
`can't find a token even if it exists on another network (%s)`,
anotherNetwork => {
const tokenBalance = hedgehoge(mockImplicitAddress(0));
@@ -58,7 +58,7 @@ describe("useGetToken", () => {
});
describe("useGetTokenType", () => {
- SupportedNetworks.forEach(network => {
+ DefaultNetworks.forEach(network => {
describe(`on ${network}`, () => {
it("returns undefined if contract is not found", () => {
const { result: getTokenRef } = renderHook(() => useGetTokenType(network), {
@@ -76,7 +76,7 @@ describe("useGetTokenType", () => {
expect(getTokenRef.current(tokenBalance.token.contract.address as string)).toEqual("fa1.2");
});
- SupportedNetworks.forEach(anotherNetwork => {
+ DefaultNetworks.forEach(anotherNetwork => {
if (anotherNetwork === network) {
return;
}
diff --git a/src/utils/hooks/tokensHooks.ts b/src/utils/hooks/tokensHooks.ts
index 2553a23c9..4be213dc4 100644
--- a/src/utils/hooks/tokensHooks.ts
+++ b/src/utils/hooks/tokensHooks.ts
@@ -1,22 +1,22 @@
import { get } from "lodash";
import { RawPkh } from "../../types/Address";
-import { TezosNetwork } from "../../types/TezosNetwork";
+import { Network } from "../../types/Network";
import { Token } from "../../types/Token";
import { useAppSelector } from "../redux/hooks";
-import { useSelectedNetwork } from "./assetsHooks";
+import { useSelectedNetwork } from "./networkHooks";
export type TokenLookup = (contract: RawPkh, tokenId: string) => Token | undefined;
export const useGetToken = (): TokenLookup => {
const network = useSelectedNetwork();
- const tokens = useAppSelector(s => s.tokens[network]);
+ const tokens = useAppSelector(s => s.tokens[network.name]);
return (contract, tokenId) => get(tokens, [contract, tokenId]);
};
-export const useGetTokenType = (network: TezosNetwork) => {
- const tokens = useAppSelector(s => s.tokens[network]);
+export const useGetTokenType = (network: Network) => {
+ const tokens = useAppSelector(s => s.tokens[network.name]);
return (contract: RawPkh): Token["type"] | undefined => {
- if (!(contract in tokens)) {
+ if (!(tokens && contract in tokens)) {
return undefined;
}
const contractTokens = tokens[contract];
diff --git a/src/utils/mnemonic.test.ts b/src/utils/mnemonic.test.ts
index 8677f3013..b6e1e0c62 100644
--- a/src/utils/mnemonic.test.ts
+++ b/src/utils/mnemonic.test.ts
@@ -7,6 +7,7 @@ import {
defaultDerivationPathPattern,
getDefaultDerivationPath,
} from "./account/derivationPathUtils";
+import { MAINNET } from "../types/Network";
const addressExistsMock = jest.mocked(addressExists);
const getFingerPrintMock = jest.mocked(getFingerPrint);
@@ -21,7 +22,11 @@ describe("restoreAccounts", () => {
addressExistsMock.mockResolvedValueOnce(true);
addressExistsMock.mockResolvedValueOnce(true);
addressExistsMock.mockResolvedValueOnce(false);
- const result = await restoreRevealedPublickKeyPairs(mnemonic1, defaultDerivationPathPattern);
+ const result = await restoreRevealedPublickKeyPairs(
+ mnemonic1,
+ defaultDerivationPathPattern,
+ MAINNET
+ );
const expected = [
{
pk: "edpkuwYWCugiYG7nMnVUdopFmyc3sbMSiLqsJHTQgGtVhtSdLSw6HG",
@@ -41,7 +46,11 @@ describe("restoreAccounts", () => {
it("should restore first account if none exists", async () => {
addressExistsMock.mockResolvedValueOnce(false);
- const result = await restoreRevealedPublickKeyPairs(mnemonic1, defaultDerivationPathPattern);
+ const result = await restoreRevealedPublickKeyPairs(
+ mnemonic1,
+ defaultDerivationPathPattern,
+ MAINNET
+ );
const expected = [
{
pk: "edpkuwYWCugiYG7nMnVUdopFmyc3sbMSiLqsJHTQgGtVhtSdLSw6HG",
@@ -59,7 +68,7 @@ describe("restoreEncryptedAccounts", () => {
addressExistsMock.mockResolvedValueOnce(true);
addressExistsMock.mockResolvedValueOnce(true);
addressExistsMock.mockResolvedValueOnce(false);
- const result = await restoreRevealedMnemonicAccounts(mnemonic1);
+ const result = await restoreRevealedMnemonicAccounts(mnemonic1, MAINNET);
const expected: ImplicitAccount[] = [
{
curve: "ed25519",
@@ -98,7 +107,7 @@ describe("restoreEncryptedAccounts", () => {
it("should restore exising accounts with a provided label", async () => {
const CUSTOM_LABEL = "myLabel";
addressExistsMock.mockResolvedValueOnce(false);
- const result = await restoreRevealedMnemonicAccounts(mnemonic1, CUSTOM_LABEL);
+ const result = await restoreRevealedMnemonicAccounts(mnemonic1, MAINNET, CUSTOM_LABEL);
const expected: ImplicitAccount[] = [
expect.objectContaining({
label: CUSTOM_LABEL,
@@ -109,7 +118,7 @@ describe("restoreEncryptedAccounts", () => {
addressExistsMock.mockResolvedValueOnce(true);
addressExistsMock.mockResolvedValueOnce(true);
addressExistsMock.mockResolvedValueOnce(false);
- const result2 = await restoreRevealedMnemonicAccounts(mnemonic1, CUSTOM_LABEL);
+ const result2 = await restoreRevealedMnemonicAccounts(mnemonic1, MAINNET, CUSTOM_LABEL);
const expected2: ImplicitAccount[] = [
expect.objectContaining({
label: `${CUSTOM_LABEL} 0`,
@@ -125,7 +134,12 @@ describe("restoreEncryptedAccounts", () => {
addressExistsMock.mockResolvedValueOnce(true);
addressExistsMock.mockResolvedValueOnce(true);
addressExistsMock.mockResolvedValueOnce(false);
- const result = await restoreRevealedMnemonicAccounts(mnemonic1, undefined, "44'/1729'/?'/0'");
+ const result = await restoreRevealedMnemonicAccounts(
+ mnemonic1,
+ MAINNET,
+ undefined,
+ "44'/1729'/?'/0'"
+ );
const expected: ImplicitAccount[] = [
expect.objectContaining({
@@ -144,7 +158,7 @@ describe("restoreEncryptedAccounts", () => {
addressExistsMock.mockResolvedValueOnce(true);
addressExistsMock.mockResolvedValueOnce(true);
addressExistsMock.mockResolvedValueOnce(false);
- const result = restoreRevealedMnemonicAccounts(mnemonic1, undefined, "44'/foo'/?'/8'");
+ const result = restoreRevealedMnemonicAccounts(mnemonic1, MAINNET, undefined, "44'/foo'/?'/8'");
await expect(result).rejects.toThrowError("Invalid derivation pattern: 44'/foo'/?'/8'");
});
diff --git a/src/utils/mnemonic.ts b/src/utils/mnemonic.ts
index 2f388fb35..bb724575b 100644
--- a/src/utils/mnemonic.ts
+++ b/src/utils/mnemonic.ts
@@ -4,6 +4,7 @@ import { defaultDerivationPathPattern, makeDerivationPath } from "./account/deri
import { makeMnemonicAccount } from "./account/makeMnemonicAccount";
import { addressExists, getFingerPrint } from "./tezos";
import { generateMnemonic } from "bip39";
+import { Network } from "../types/Network";
// This is put in a separate file for mocking purposes in tests
export const generate24WordMnemonic = () => {
@@ -41,16 +42,18 @@ export const deriveSecretKey = (mnemonic: string, derivationPath: string, curve:
export const restoreRevealedPublickKeyPairs = async (
mnemonic: string,
derivationPathPattern: string,
+ network: Network,
result: PublicKeyPair[] = [],
startIndex = 0
): Promise => {
const derivationPath = makeDerivationPath(derivationPathPattern, startIndex);
const pubKeyPair = await derivePublicKeyPair(mnemonic, derivationPath);
- if (await addressExists(pubKeyPair.pkh)) {
+ if (await addressExists(pubKeyPair.pkh, network)) {
return restoreRevealedPublickKeyPairs(
mnemonic,
derivationPathPattern,
+ network,
[...result, pubKeyPair],
startIndex + 1
);
@@ -61,10 +64,15 @@ export const restoreRevealedPublickKeyPairs = async (
export const restoreRevealedMnemonicAccounts = async (
mnemonic: string,
+ network: Network,
label = "Account",
derivationPathPattern = defaultDerivationPathPattern
): Promise => {
- const pubKeyPairs = await restoreRevealedPublickKeyPairs(mnemonic, derivationPathPattern);
+ const pubKeyPairs = await restoreRevealedPublickKeyPairs(
+ mnemonic,
+ derivationPathPattern,
+ network
+ );
const seedFingerPrint = await getFingerPrint(mnemonic);
return pubKeyPairs.map(({ pk, pkh }, i) => {
diff --git a/src/utils/multisig/fetch.test.ts b/src/utils/multisig/fetch.test.ts
index 656a0e256..480131dc1 100644
--- a/src/utils/multisig/fetch.test.ts
+++ b/src/utils/multisig/fetch.test.ts
@@ -1,8 +1,7 @@
import axios from "axios";
import { ghostMultisigContracts } from "../../mocks/tzktResponse";
-import { TezosNetwork } from "../../types/TezosNetwork";
-import { tzktUrls } from "../tezos/consts";
import { getAllMultiSigContracts } from "./fetch";
+import { GHOSTNET } from "../../types/Network";
jest.mock("axios");
@@ -12,11 +11,9 @@ describe("multisig fetch", () => {
test("getAllMultiSigContracts", async () => {
mockedAxios.get.mockResolvedValue({ data: ghostMultisigContracts });
- const result = await getAllMultiSigContracts(TezosNetwork.GHOSTNET);
+ const result = await getAllMultiSigContracts(GHOSTNET);
expect(mockedAxios.get).toBeCalledWith(
- `${
- tzktUrls[TezosNetwork.GHOSTNET]
- }/v1/contracts?typeHash=1963879877&codeHash=-1890025422&includeStorage=true&limit=10000`
+ `${GHOSTNET.tzktApiUrl}/v1/contracts?typeHash=1963879877&codeHash=-1890025422&includeStorage=true&limit=10000`
);
expect(
result.map(({ address, storage: { pending_ops, signers, threshold } }) => ({
diff --git a/src/utils/multisig/fetch.ts b/src/utils/multisig/fetch.ts
index 5bc223c4c..0b7851c97 100644
--- a/src/utils/multisig/fetch.ts
+++ b/src/utils/multisig/fetch.ts
@@ -1,16 +1,15 @@
import axios from "axios";
-import { TezosNetwork } from "../../types/TezosNetwork";
-import { tzktUrls } from "../tezos/consts";
+import { Network } from "../../types/Network";
import { RawTzktGetBigMapKeys, RawTzktGetSameMultisigs } from "../tzkt/types";
const MULTISIG_FETCH_LIMIT = 10000;
const TYPE_HASH = 1963879877;
const CODE_HASH = -1890025422;
export const getAllMultiSigContracts = async (
- network: TezosNetwork
+ network: Network
): Promise => {
try {
- const url = `${tzktUrls[network]}/v1/contracts?typeHash=${TYPE_HASH}&codeHash=${CODE_HASH}&includeStorage=true&limit=${MULTISIG_FETCH_LIMIT}`;
+ const url = `${network.tzktApiUrl}/v1/contracts?typeHash=${TYPE_HASH}&codeHash=${CODE_HASH}&includeStorage=true&limit=${MULTISIG_FETCH_LIMIT}`;
const { data } = await axios.get(url);
return data;
@@ -22,9 +21,9 @@ export const getAllMultiSigContracts = async (
// get all pending operations for a multisig contract address
export const getPendingOperations = async (
bigMaps: number[],
- network: TezosNetwork
+ network: Network
): Promise => {
- const url = `${tzktUrls[network]}/v1/bigmaps/keys?active=true&bigmap.in=${bigMaps.join(
+ const url = `${network.tzktApiUrl}/v1/bigmaps/keys?active=true&bigmap.in=${bigMaps.join(
","
)}&limit=${MULTISIG_FETCH_LIMIT}`;
const { data } = await axios.get(url);
diff --git a/src/utils/multisig/helper.test.ts b/src/utils/multisig/helper.test.ts
index 997cae606..00b1c31c0 100644
--- a/src/utils/multisig/helper.test.ts
+++ b/src/utils/multisig/helper.test.ts
@@ -6,13 +6,13 @@ import {
parseMultisig,
} from "./helpers";
import { tzktGetSameMultisigsResponse } from "../../mocks/tzktResponse";
-import { SupportedNetworks } from "../network";
+import { DefaultNetworks } from "../../types/Network";
jest.mock("axios");
const mockedAxios = axios as jest.Mocked;
describe("multisig helpers", () => {
- SupportedNetworks.forEach(async network => {
+ DefaultNetworks.forEach(async network => {
test("getRelevantMultisigContracts", async () => {
const mockResponse = {
data: tzktGetSameMultisigsResponse,
@@ -57,7 +57,7 @@ describe("multisig helpers", () => {
);
expect(mockedAxios.get).toBeCalledWith(
- `https://api.${network}.tzkt.io/v1/bigmaps/keys?active=true&bigmap.in=0,1&limit=10000`
+ `${network.tzktApiUrl}/v1/bigmaps/keys?active=true&bigmap.in=0,1&limit=10000`
);
expect(result).toEqual([
diff --git a/src/utils/multisig/helpers.ts b/src/utils/multisig/helpers.ts
index 4cd8a5f77..4bd9a0a54 100644
--- a/src/utils/multisig/helpers.ts
+++ b/src/utils/multisig/helpers.ts
@@ -4,7 +4,7 @@ import { parseContractPkh, parseImplicitPkh } from "../../types/Address";
import { RawTzktGetBigMapKeysItem, RawTzktGetSameMultisigsItem } from "../tzkt/types";
import { getAllMultiSigContracts, getPendingOperations } from "./fetch";
import { Multisig, MultisigOperation } from "./types";
-import { TezosNetwork } from "../../types/TezosNetwork";
+import { Network } from "../../types/Network";
export const parseMultisig = (raw: RawTzktGetSameMultisigsItem): Multisig => ({
address: parseContractPkh(raw.address),
@@ -16,7 +16,7 @@ export const parseMultisig = (raw: RawTzktGetSameMultisigsItem): Multisig => ({
export const getRelevantMultisigContracts = async (
accountPkhs: Set,
- network: TezosNetwork
+ network: Network
): Promise =>
getAllMultiSigContracts(network).then(multisigs =>
multisigs
@@ -44,7 +44,7 @@ const parseMultisigOperation = (raw: RawTzktGetBigMapKeysItem): MultisigOperatio
export const getPendingOperationsForMultisigs = async (
multisigs: Multisig[],
- network: TezosNetwork
+ network: Network
): Promise => {
const bigmapIds = multisigs.map(m => m.pendingOperationsBigmapId);
diff --git a/src/utils/network.ts b/src/utils/network.ts
deleted file mode 100644
index be7c20787..000000000
--- a/src/utils/network.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import { TezosNetwork } from "../types/TezosNetwork";
-
-export const SupportedNetworks = [TezosNetwork.GHOSTNET, TezosNetwork.MAINNET];
diff --git a/src/utils/redux/reducer.ts b/src/utils/redux/reducer.ts
index 5ec813954..1b82f734c 100644
--- a/src/utils/redux/reducer.ts
+++ b/src/utils/redux/reducer.ts
@@ -7,6 +7,7 @@ import assetsSlice from "./slices/assetsSlice";
import contactsSlice from "./slices/contactsSlice";
import multisigsSlice from "./slices/multisigsSlice";
import errorsSlice from "./slices/errorsSlice";
+import { networksSlice } from "./slices/networks";
const rootPersistConfig = {
key: "root",
@@ -27,6 +28,7 @@ const rootReducers = combineReducers({
multisigs: multisigsSlice.reducer,
tokens: tokensSlice.reducer,
errors: errorsSlice.reducer,
+ networks: networksSlice.reducer,
});
export default persistReducer(rootPersistConfig, rootReducers);
diff --git a/src/utils/redux/slices/accountsSlice.test.ts b/src/utils/redux/slices/accountsSlice.test.ts
index 979ac872f..eba79c477 100644
--- a/src/utils/redux/slices/accountsSlice.test.ts
+++ b/src/utils/redux/slices/accountsSlice.test.ts
@@ -10,6 +10,7 @@ import { deriveAccount, restoreFromMnemonic } from "../thunks/restoreMnemonicAcc
import { getFingerPrint } from "../../tezos";
import { parseImplicitPkh } from "../../../types/Address";
import accountsSlice from "./accountsSlice";
+import { MAINNET } from "../../../types/Network";
const {
actions: { addAccount, removeMnemonicAndAccounts },
@@ -127,6 +128,7 @@ describe("Accounts reducer", () => {
expect(fakeExtraArguments.restoreRevealedMnemonicAccounts).toHaveBeenCalledWith(
mnemonic1,
+ MAINNET,
mockLabel,
undefined
);
diff --git a/src/utils/redux/slices/assetsSlice.test.ts b/src/utils/redux/slices/assetsSlice.test.ts
index 006b2279c..1d29a016a 100644
--- a/src/utils/redux/slices/assetsSlice.test.ts
+++ b/src/utils/redux/slices/assetsSlice.test.ts
@@ -13,16 +13,16 @@ import {
} from "../../../mocks/factories";
import accountsSlice from "./accountsSlice";
import { hedgehoge } from "../../../mocks/fa12Tokens";
-import { TezosNetwork } from "../../../types/TezosNetwork";
import { makeAccountOperations } from "../../../components/sendForm/types";
import { Operation } from "../../../types/Operation";
import { ImplicitOperations } from "../../../components/sendForm/types";
+import { GHOSTNET } from "../../../types/Network";
+import { networksActions } from "./networks";
const {
actions: {
updateTezBalance,
updateTokenBalance,
- updateNetwork,
updateTezTransfers,
updateTokenTransfers,
clearBatch,
@@ -40,7 +40,6 @@ describe("assetsSlice", () => {
},
transfers: { tez: {}, tokens: {} },
delegations: {},
- network: "mainnet",
conversionRate: null,
bakers: [],
batches: [],
@@ -63,7 +62,6 @@ describe("assetsSlice", () => {
},
transfers: { tez: {}, tokens: {} },
delegations: {},
- network: "mainnet",
conversionRate: null,
bakers: [],
batches: [],
@@ -90,7 +88,6 @@ describe("assetsSlice", () => {
},
transfers: { tez: {}, tokens: {} },
delegations: {},
- network: "mainnet",
conversionRate: null,
bakers: [],
batches: [],
@@ -126,7 +123,6 @@ describe("assetsSlice", () => {
conversionRate: null,
delegations: {},
bakers: [],
- network: "mainnet",
transfers: { tez: {}, tokens: {} },
batches: [],
blockLevel: null,
@@ -155,7 +151,6 @@ describe("assetsSlice", () => {
conversionRate: null,
delegations: {},
bakers: [],
- network: "mainnet",
transfers: { tez: {}, tokens: {} },
batches: [],
blockLevel: null,
@@ -165,33 +160,6 @@ describe("assetsSlice", () => {
});
});
- test("updating network resets operations and balances", () => {
- store.dispatch(
- updateTezBalance([
- { address: "bar", balance: 44 },
- { address: "baz", balance: 55 },
- ])
- );
-
- store.dispatch(updateTokenBalance([hedgehoge(mockImplicitAddress(0))]));
-
- store.dispatch(updateNetwork(TezosNetwork.GHOSTNET));
-
- expect(store.getState().assets).toEqual({
- balances: { mutez: {}, tokens: {} },
- transfers: { tez: {}, tokens: {} },
- delegations: {},
- bakers: [],
- network: "ghostnet",
- conversionRate: null,
- batches: [],
- blockLevel: null,
- refetchTrigger: 0,
- lastTimeUpdated: null,
- isLoading: false,
- });
- });
-
test("reseting accounts resets assetsState", () => {
store.dispatch(
updateTezBalance([
@@ -209,7 +177,6 @@ describe("assetsSlice", () => {
transfers: { tez: {}, tokens: {} },
delegations: {},
bakers: [],
- network: "mainnet",
conversionRate: null,
batches: [],
blockLevel: null,
@@ -238,7 +205,6 @@ describe("assetsSlice", () => {
},
delegations: {},
bakers: [],
- network: "mainnet",
batches: [],
transfers: {
tez: {
@@ -274,7 +240,6 @@ describe("assetsSlice", () => {
},
delegations: {},
bakers: [],
- network: "mainnet",
batches: [],
transfers: {
tez: {
@@ -289,7 +254,7 @@ describe("assetsSlice", () => {
lastTimeUpdated: null,
isLoading: false,
});
- store.dispatch(updateNetwork(TezosNetwork.GHOSTNET));
+ store.dispatch(networksActions.setCurrent(GHOSTNET));
});
test("token transfers are upserted", () => {
@@ -311,7 +276,6 @@ describe("assetsSlice", () => {
},
delegations: {},
bakers: [],
- network: "mainnet",
batches: [],
transfers: {
tokens: {
@@ -347,7 +311,6 @@ describe("assetsSlice", () => {
},
delegations: {},
bakers: [],
- network: "mainnet",
transfers: {
tokens: {
foo: [mockTokenTransaction(4)],
diff --git a/src/utils/redux/slices/assetsSlice.ts b/src/utils/redux/slices/assetsSlice.ts
index 320d1a7c7..16b4e8dc8 100644
--- a/src/utils/redux/slices/assetsSlice.ts
+++ b/src/utils/redux/slices/assetsSlice.ts
@@ -2,7 +2,6 @@ import { createSlice } from "@reduxjs/toolkit";
import { DelegationOperation } from "@tzkt/sdk-api";
import { compact, findIndex, groupBy, mapValues } from "lodash";
import accountsSlice from "./accountsSlice";
-import { TezosNetwork } from "../../../types/TezosNetwork";
import { TezTransfer, TokenTransfer } from "../../../types/Transfer";
import { TzktAccount } from "../../tezos";
import { fromRaw, RawTokenBalance, TokenBalance } from "../../../types/TokenBalance";
@@ -11,7 +10,6 @@ import { AccountOperations } from "../../../components/sendForm/types";
import { RawPkh } from "../../../types/Address";
type State = {
- network: TezosNetwork;
blockLevel: number | null;
balances: {
mutez: Record;
@@ -47,7 +45,6 @@ export type DelegationPayload = {
export type ConversionRatePayload = { rate: State["conversionRate"] };
const initialState: State = {
- network: TezosNetwork.MAINNET,
blockLevel: null,
balances: {
mutez: {},
@@ -77,9 +74,6 @@ const assetsSlice = createSlice({
builder.addCase(accountsSlice.actions.reset, () => initialState),
reducers: {
reset: () => initialState,
- updateNetwork: (_, { payload }: { type: string; payload: TezosNetwork }) => {
- return { ...initialState, network: payload };
- },
updateBlockLevel: (state, { payload }: { payload: number }) => {
state.blockLevel = payload;
},
diff --git a/src/utils/redux/slices/networks.test.ts b/src/utils/redux/slices/networks.test.ts
new file mode 100644
index 000000000..c1ab43a63
--- /dev/null
+++ b/src/utils/redux/slices/networks.test.ts
@@ -0,0 +1,17 @@
+import { DefaultNetworks, GHOSTNET, MAINNET } from "../../../types/Network";
+import store from "../store";
+import { networksActions } from "./networks";
+
+describe("networksSlice", () => {
+ test("initialState", () => {
+ expect(store.getState().networks).toEqual({
+ available: DefaultNetworks,
+ current: MAINNET,
+ });
+ });
+
+ test("setCurrent", () => {
+ store.dispatch(networksActions.setCurrent(GHOSTNET));
+ expect(store.getState().networks.current).toEqual(GHOSTNET);
+ });
+});
diff --git a/src/utils/redux/slices/networks.ts b/src/utils/redux/slices/networks.ts
new file mode 100644
index 000000000..9c0869374
--- /dev/null
+++ b/src/utils/redux/slices/networks.ts
@@ -0,0 +1,24 @@
+import { createSlice } from "@reduxjs/toolkit";
+import { DefaultNetworks, MAINNET, Network } from "../../../types/Network";
+
+type State = {
+ available: Network[];
+ current: Network;
+};
+
+const initialState: State = {
+ available: DefaultNetworks,
+ current: MAINNET,
+};
+
+export const networksSlice = createSlice({
+ name: "networks",
+ initialState,
+ reducers: {
+ reset: () => initialState,
+ setCurrent: (state, { payload }: { payload: Network }) => {
+ state.current = payload;
+ },
+ },
+});
+export const networksActions = networksSlice.actions;
diff --git a/src/utils/redux/slices/tokensSlice.ts b/src/utils/redux/slices/tokensSlice.ts
index 8928b1bdb..52411a828 100644
--- a/src/utils/redux/slices/tokensSlice.ts
+++ b/src/utils/redux/slices/tokensSlice.ts
@@ -1,15 +1,12 @@
import { createSlice } from "@reduxjs/toolkit";
-import { compact, setWith } from "lodash";
+import { compact, fromPairs, setWith } from "lodash";
import { RawPkh } from "../../../types/Address";
-import { TezosNetwork } from "../../../types/TezosNetwork";
+import { DefaultNetworks, Network, NetworkName } from "../../../types/Network";
import { fromRaw, RawTokenInfo, Token, TokenId } from "../../../types/Token";
-type State = Record>>;
+type State = Record> | undefined>;
-const initialState: State = {
- [TezosNetwork.MAINNET]: {},
- [TezosNetwork.GHOSTNET]: {},
-};
+const initialState: State = fromPairs(DefaultNetworks.map(network => [network, {}]));
const tokensSlice = createSlice({
name: "tokens",
@@ -18,12 +15,10 @@ const tokensSlice = createSlice({
reset: () => initialState,
addTokens: (
state: State,
- {
- payload: { network, tokens },
- }: { payload: { network: TezosNetwork; tokens: RawTokenInfo[] } }
+ { payload: { network, tokens } }: { payload: { network: Network; tokens: RawTokenInfo[] } }
) => {
compact(tokens.map(fromRaw)).forEach(token => {
- setWith(state, [network, token.contract, token.tokenId], token, Object);
+ setWith(state, [network.name, token.contract, token.tokenId], token, Object);
});
},
},
diff --git a/src/utils/redux/thunks/estimateAndUpdateBatch.test.ts b/src/utils/redux/thunks/estimateAndUpdateBatch.test.ts
index 11da506a7..2018c3bf7 100644
--- a/src/utils/redux/thunks/estimateAndUpdateBatch.test.ts
+++ b/src/utils/redux/thunks/estimateAndUpdateBatch.test.ts
@@ -6,13 +6,13 @@ import {
mockTezOperation,
} from "../../../mocks/factories";
import { mockEstimatedFee } from "../../../mocks/helpers";
-import { SupportedNetworks } from "../../network";
import { estimate } from "../../tezos";
import store from "../store";
import { estimateAndUpdateBatch } from "./estimateAndUpdateBatch";
+import { DefaultNetworks } from "../../../types/Network";
describe("estimateAndUpdateBatch", () => {
- describe.each(SupportedNetworks)("on %s", network => {
+ describe.each(DefaultNetworks)("on $name", network => {
it("adds an operation to batch if the estimation succeeds", async () => {
const operation = mockTezOperation(1);
diff --git a/src/utils/redux/thunks/estimateAndUpdateBatch.ts b/src/utils/redux/thunks/estimateAndUpdateBatch.ts
index 24c5c90e7..89865690f 100644
--- a/src/utils/redux/thunks/estimateAndUpdateBatch.ts
+++ b/src/utils/redux/thunks/estimateAndUpdateBatch.ts
@@ -1,13 +1,13 @@
import { AnyAction, ThunkAction } from "@reduxjs/toolkit";
import { AccountOperations } from "../../../components/sendForm/types";
-import { TezosNetwork } from "../../../types/TezosNetwork";
+import { Network } from "../../../types/Network";
import { estimate } from "../../tezos";
import assetsSlice from "../slices/assetsSlice";
import { RootState } from "../store";
export const estimateAndUpdateBatch = (
operations: AccountOperations,
- network: TezosNetwork
+ network: Network
): ThunkAction, RootState, unknown, AnyAction> => {
return async dispatch => {
// check that the operation can be executed at least on its own
diff --git a/src/utils/redux/thunks/restoreMnemonicAccounts.ts b/src/utils/redux/thunks/restoreMnemonicAccounts.ts
index 166696fa3..669a8579a 100644
--- a/src/utils/redux/thunks/restoreMnemonicAccounts.ts
+++ b/src/utils/redux/thunks/restoreMnemonicAccounts.ts
@@ -6,6 +6,7 @@ import { EncryptedData } from "../../crypto/types";
import { getFingerPrint } from "../../tezos";
import { ExtraArgument } from "../extraArgument";
import { AppDispatch, RootState } from "../store";
+import { MAINNET } from "../../../types/Network";
export const restoreFromMnemonic = createAsyncThunk<
{
@@ -28,6 +29,7 @@ export const restoreFromMnemonic = createAsyncThunk<
seedFingerprint: await getFingerPrint(seedPhrase),
accounts: await thunkAPI.extra.restoreRevealedMnemonicAccounts(
seedPhrase,
+ MAINNET, // TODO: consider choosing network on onboarding
label,
derivationPathPattern
),
diff --git a/src/utils/tezos/consts.ts b/src/utils/tezos/consts.ts
index 841e38033..98065eead 100644
--- a/src/utils/tezos/consts.ts
+++ b/src/utils/tezos/consts.ts
@@ -1,25 +1,3 @@
-import { TezosNetwork } from "../../types/TezosNetwork";
-
-export const nodeUrls = {
- [TezosNetwork.GHOSTNET]: `https://tezos-ghostnet-node.prod.gke.papers.tech`,
- [TezosNetwork.MAINNET]: `https://mainnet.api.tez.ie`,
-};
-
-export const tzktUrls = {
- [TezosNetwork.GHOSTNET]: `https://api.ghostnet.tzkt.io`,
- [TezosNetwork.MAINNET]: `https://api.mainnet.tzkt.io`,
-};
-
-export const tzktExplorer = {
- [TezosNetwork.GHOSTNET]: `https://ghostnet.tzkt.io`,
- [TezosNetwork.MAINNET]: `https://tzkt.io`,
-};
-
-export const wertUrls = {
- [TezosNetwork.GHOSTNET]: `https://faucet.ghostnet.teztnets.xyz/`,
- [TezosNetwork.MAINNET]: `https://widget.wert.io`,
-};
-
export const coincapUrl = "https://api.coincap.io/v2/assets";
export const TEZ = "ꜩ";
diff --git a/src/utils/tezos/estimate.ts b/src/utils/tezos/estimate.ts
index 517d21da0..94ab0eed1 100644
--- a/src/utils/tezos/estimate.ts
+++ b/src/utils/tezos/estimate.ts
@@ -1,11 +1,11 @@
import { AccountOperations } from "../../components/sendForm/types";
-import { TezosNetwork } from "../../types/TezosNetwork";
+import { Network } from "../../types/Network";
import { makeToolkit, operationsToBatchParams, sumTez } from "./helpers";
import BigNumber from "bignumber.js";
export const estimate = async (
operations: AccountOperations,
- network: TezosNetwork
+ network: Network
): Promise => {
const tezosToolkit = await makeToolkit({ type: "fake", signer: operations.signer, network });
diff --git a/src/utils/tezos/fetch.test.ts b/src/utils/tezos/fetch.test.ts
index 7fbc088bf..b9535346e 100644
--- a/src/utils/tezos/fetch.test.ts
+++ b/src/utils/tezos/fetch.test.ts
@@ -8,12 +8,11 @@ import {
getTokenTransfers,
} from "./fetch";
import { operationsGetTransactions, tokensGetTokenTransfers } from "@tzkt/sdk-api";
-import { coincapUrl, tzktUrls } from "./consts";
+import { coincapUrl } from "./consts";
import { mockContractAddress, mockImplicitAddress } from "../../mocks/factories";
-import { SupportedNetworks } from "../network";
import { hedgehoge, tzBtsc } from "../../mocks/fa12Tokens";
import { uUSD } from "../../mocks/fa2Tokens";
-import { TezosNetwork } from "../../types/TezosNetwork";
+import { DefaultNetworks } from "../../types/Network";
jest.mock("axios");
jest.mock("@tzkt/sdk-api", () => {
@@ -28,33 +27,33 @@ jest.mock("@tzkt/sdk-api", () => {
const mockedAxios = axios as jest.Mocked;
describe("tezos utils fetch", () => {
- test("getTezosPriceInUSD", async () => {
- const mockResponse = {
- data: {
+ describe.each(DefaultNetworks)("on $name", network => {
+ test("getTezosPriceInUSD", async () => {
+ const mockResponse = {
data: {
- id: "tezos",
- rank: "45",
- symbol: "XTZ",
- name: "Tezos",
- supply: "934953037.6018340000000000",
- maxSupply: null,
- marketCapUsd: "973524588.0822762611894168",
- volumeUsd24Hr: "11804202.6168944408092813",
- priceUsd: "1.0412550672912714",
- changePercent24Hr: "-1.7557594377565521",
- vwap24Hr: "1.0421183688213239",
- explorer: "https://tzkt.io/",
+ data: {
+ id: "tezos",
+ rank: "45",
+ symbol: "XTZ",
+ name: "Tezos",
+ supply: "934953037.6018340000000000",
+ maxSupply: null,
+ marketCapUsd: "973524588.0822762611894168",
+ volumeUsd24Hr: "11804202.6168944408092813",
+ priceUsd: "1.0412550672912714",
+ changePercent24Hr: "-1.7557594377565521",
+ vwap24Hr: "1.0421183688213239",
+ explorer: "https://tzkt.io/",
+ },
},
- },
- };
- mockedAxios.get.mockResolvedValue(mockResponse);
- const result = await getTezosPriceInUSD();
- expect(mockedAxios.get).toBeCalledWith(`${coincapUrl}/tezos`);
- expect(result).toEqual(mockResponse.data.data.priceUsd);
- });
+ };
+ mockedAxios.get.mockResolvedValue(mockResponse);
+ const result = await getTezosPriceInUSD();
+ expect(mockedAxios.get).toBeCalledWith(`${coincapUrl}/tezos`);
+ expect(result).toEqual(mockResponse.data.data.priceUsd);
+ });
- test("getTokenBalances", async () => {
- SupportedNetworks.forEach(async network => {
+ test("getTokenBalances", async () => {
const response = [
hedgehoge(mockImplicitAddress(0)),
uUSD(mockImplicitAddress(1)),
@@ -69,50 +68,46 @@ describe("tezos utils fetch", () => {
];
const res = await getTokenBalances(addresses, network);
expect(mockedAxios.get).toBeCalledWith(
- `https://api.${network}.tzkt.io/v1/tokens/balances?account.in=${addresses.join(
- ","
- )}&balance.gt=0`
+ `${network.tzktApiUrl}/v1/tokens/balances?account.in=${addresses.join(",")}&balance.gt=0`
);
expect(res).toEqual(response);
});
- });
- test("getTezTransfers", async () => {
- await getTezTransfers(mockImplicitAddress(0).pkh, TezosNetwork.GHOSTNET);
- expect(operationsGetTransactions).toBeCalledWith(
- {
- anyof: { fields: ["sender", "target"], eq: mockImplicitAddress(0).pkh },
- sort: { desc: "level" },
- limit: 10,
- },
- {
- baseUrl: tzktUrls[TezosNetwork.GHOSTNET],
- }
- );
- });
+ test("getTezTransfers", async () => {
+ await getTezTransfers(mockImplicitAddress(0).pkh, network);
+ expect(operationsGetTransactions).toBeCalledWith(
+ {
+ anyof: { fields: ["sender", "target"], eq: mockImplicitAddress(0).pkh },
+ sort: { desc: "level" },
+ limit: 10,
+ },
+ {
+ baseUrl: network.tzktApiUrl,
+ }
+ );
+ });
- test("getTokenTransfers", async () => {
- await getTokenTransfers(mockImplicitAddress(0).pkh, TezosNetwork.GHOSTNET);
- expect(tokensGetTokenTransfers).toBeCalledWith(
- {
- anyof: { fields: ["from", "to"], eq: mockImplicitAddress(0).pkh },
- sort: { desc: "level" },
- limit: 10,
- },
- {
- baseUrl: tzktUrls[TezosNetwork.GHOSTNET],
- }
- );
- });
+ test("getTokenTransfers", async () => {
+ await getTokenTransfers(mockImplicitAddress(0).pkh, network);
+ expect(tokensGetTokenTransfers).toBeCalledWith(
+ {
+ anyof: { fields: ["from", "to"], eq: mockImplicitAddress(0).pkh },
+ sort: { desc: "level" },
+ limit: 10,
+ },
+ {
+ baseUrl: network.tzktApiUrl,
+ }
+ );
+ });
- test("getLastDelegation", async () => {
- const res = await getLastDelegation(mockImplicitAddress(0).pkh, TezosNetwork.GHOSTNET);
- expect(res).toEqual({ type: "delegation" });
- });
+ test("getLastDelegation", async () => {
+ const res = await getLastDelegation(mockImplicitAddress(0).pkh, network);
+ expect(res).toEqual({ type: "delegation" });
+ });
- test("getAccounts", async () => {
- SupportedNetworks.forEach(async network => {
+ test("getAccounts", async () => {
mockedAxios.get.mockResolvedValue({
data: [
{ address: mockImplicitAddress(0).pkh, balance: 12345 },
@@ -126,9 +121,7 @@ describe("tezos utils fetch", () => {
];
const res = await getAccounts(addresses, network);
expect(mockedAxios.get).toBeCalledWith(
- `https://api.${network}.tzkt.io/v1/accounts?address.in=${addresses.join(
- ","
- )}&select=address,balance`
+ `${network.tzktApiUrl}/v1/accounts?address.in=${addresses.join(",")}&select=address,balance`
);
expect(res).toEqual([
diff --git a/src/utils/tezos/fetch.ts b/src/utils/tezos/fetch.ts
index 02dd5dc77..668d97ed8 100644
--- a/src/utils/tezos/fetch.ts
+++ b/src/utils/tezos/fetch.ts
@@ -9,41 +9,35 @@ import {
TokenTransfer,
} from "@tzkt/sdk-api";
import axios from "axios";
-import { coincapUrl, tzktUrls } from "./consts";
+import { coincapUrl } from "./consts";
import { coinCapResponseType } from "./types";
import { TezTransfer } from "../../types/Transfer";
import { RawTokenBalance } from "../../types/TokenBalance";
-import { TezosNetwork } from "../../types/TezosNetwork";
+import { Network } from "../../types/Network";
// TzKT defines type Account = {type: string};
// whilst accountsGet returns all the info about accounts
// for now we need only the balance, but we can extend it later
export type TzktAccount = { address: string; balance: number };
-export const getAccounts = async (
- pkhs: string[],
- network: TezosNetwork
-): Promise => {
+export const getAccounts = async (pkhs: string[], network: Network): Promise => {
const response = await axios.get(
- `${tzktUrls[network]}/v1/accounts?address.in=${pkhs.join(",")}&select=address,balance`
+ `${network.tzktApiUrl}/v1/accounts?address.in=${pkhs.join(",")}&select=address,balance`
);
return response.data;
};
export const getTokenBalances = async (
pkhs: string[],
- network: TezosNetwork
+ network: Network
): Promise => {
const response = await axios.get(
- `${tzktUrls[network]}/v1/tokens/balances?account.in=${pkhs.join(",")}&balance.gt=0`
+ `${network.tzktApiUrl}/v1/tokens/balances?account.in=${pkhs.join(",")}&balance.gt=0`
);
return response.data;
};
-export const getTezTransfers = (
- address: string,
- network = TezosNetwork.MAINNET
-): Promise => {
+export const getTezTransfers = (address: string, network: Network): Promise => {
return operationsGetTransactions(
{
anyof: { fields: ["sender", "target"], eq: address },
@@ -51,15 +45,12 @@ export const getTezTransfers = (
limit: 10,
},
{
- baseUrl: tzktUrls[network],
+ baseUrl: network.tzktApiUrl,
}
);
};
-export const getTokenTransfers = (
- address: string,
- network = TezosNetwork.MAINNET
-): Promise => {
+export const getTokenTransfers = (address: string, network: Network): Promise => {
return tokensGetTokenTransfers(
{
anyof: { fields: ["from", "to"], eq: address },
@@ -67,14 +58,14 @@ export const getTokenTransfers = (
limit: 10,
},
{
- baseUrl: tzktUrls[network],
+ baseUrl: network.tzktApiUrl,
}
);
};
export const getLastDelegation = async (
address: string,
- network = TezosNetwork.MAINNET
+ network: Network
): Promise => {
return operationsGetDelegations(
{
@@ -83,7 +74,7 @@ export const getLastDelegation = async (
limit: 1,
},
{
- baseUrl: tzktUrls[network],
+ baseUrl: network.tzktApiUrl,
}
).then(d => d[0]);
};
@@ -100,13 +91,13 @@ export const getTezosPriceInUSD = async (): Promise => {
return priceUsd ?? null;
};
-export const getLatestBlockLevel = async (network = TezosNetwork.MAINNET): Promise => {
+export const getLatestBlockLevel = async (network: Network): Promise => {
return await blocksGetCount({
- baseUrl: tzktUrls[network],
+ baseUrl: network.tzktApiUrl,
});
};
-export const getBakers = async (network: TezosNetwork): Promise => {
+export const getBakers = async (network: Network): Promise => {
return delegatesGet(
{
sort: { desc: "stakingBalance" },
@@ -115,7 +106,7 @@ export const getBakers = async (network: TezosNetwork): Promise => {
select: { fields: ["address,alias,stakingBalance"] },
},
{
- baseUrl: tzktUrls[network],
+ baseUrl: network.tzktApiUrl,
}
);
};
diff --git a/src/utils/tezos/helpers.test.ts b/src/utils/tezos/helpers.test.ts
index 637a79c6f..b0f73d5cc 100644
--- a/src/utils/tezos/helpers.test.ts
+++ b/src/utils/tezos/helpers.test.ts
@@ -17,7 +17,6 @@ import {
FA12Transfer,
FA2Transfer,
} from "../../types/Operation";
-import { tzktUrls } from "./consts";
import {
addressExists,
getPkAndPkhFromSk,
@@ -27,6 +26,7 @@ import {
operationsToBatchParams,
} from "./helpers";
import { makeAccountOperations } from "../../components/sendForm/types";
+import { MAINNET } from "../../types/Network";
jest.mock("@taquito/signer");
jest.mock("./fakeSigner");
jest.mock("axios");
@@ -46,9 +46,9 @@ describe("tezos utils helpers", () => {
},
};
mockedAxios.get.mockResolvedValue(mockResponse);
- const result = await addressExists(mockImplicitAddress(0).pkh);
+ const result = await addressExists(mockImplicitAddress(0).pkh, MAINNET);
expect(mockedAxios.get).toBeCalledWith(
- `${tzktUrls.mainnet}/v1/accounts/${mockImplicitAddress(0).pkh}`
+ `${MAINNET.tzktApiUrl}/v1/accounts/${mockImplicitAddress(0).pkh}`
);
expect(result).toEqual(true);
});
@@ -60,9 +60,9 @@ describe("tezos utils helpers", () => {
},
};
mockedAxios.get.mockResolvedValue(mockResponse);
- const result = await addressExists(mockImplicitAddress(0).pkh);
+ const result = await addressExists(mockImplicitAddress(0).pkh, MAINNET);
expect(mockedAxios.get).toBeCalledWith(
- `${tzktUrls.mainnet}/v1/accounts/${mockImplicitAddress(0).pkh}`
+ `${MAINNET.tzktApiUrl}/v1/accounts/${mockImplicitAddress(0).pkh}`
);
expect(result).toEqual(false);
});
diff --git a/src/utils/tezos/helpers.ts b/src/utils/tezos/helpers.ts
index 17f8ddb4c..ca33b31b6 100644
--- a/src/utils/tezos/helpers.ts
+++ b/src/utils/tezos/helpers.ts
@@ -11,21 +11,17 @@ import {
makeMultisigProposeOperation,
} from "../../types/Operation";
import { SignerConfig } from "../../types/SignerConfig";
-import { TezosNetwork } from "../../types/TezosNetwork";
import { PublicKeyPair } from "../mnemonic";
import { RawTzktGetAddressType } from "../tzkt/types";
-import { nodeUrls, tzktUrls } from "./consts";
import { FakeSigner } from "./fakeSigner";
import BigNumber from "bignumber.js";
import { OpKind, TransactionOperationParameter } from "@taquito/rpc";
import { AccountOperations } from "../../components/sendForm/types";
+import { Network } from "../../types/Network";
-export const addressExists = async (
- pkh: string,
- network = TezosNetwork.MAINNET
-): Promise => {
+export const addressExists = async (pkh: string, network: Network): Promise => {
try {
- const url = `${tzktUrls[network]}/v1/accounts/${pkh}`;
+ const url = `${network.tzktApiUrl}/v1/accounts/${pkh}`;
const {
data: { type },
} = await axios.get(url);
@@ -87,7 +83,7 @@ export const makeSigner = async (config: SignerConfig) => {
};
export const makeToolkit = async (config: SignerConfig) => {
- const toolkit = new TezosToolkit(nodeUrls[config.network]);
+ const toolkit = new TezosToolkit(config.network.rpcUrl);
const signer = await makeSigner(config);
toolkit.setSignerProvider(signer);
return toolkit;
diff --git a/src/utils/tzkt/helpers.test.ts b/src/utils/tzkt/helpers.test.ts
index 2d5869400..6c8cf21b6 100644
--- a/src/utils/tzkt/helpers.test.ts
+++ b/src/utils/tzkt/helpers.test.ts
@@ -1,11 +1,9 @@
-import { TezosNetwork } from "../../types/TezosNetwork";
+import { GHOSTNET, MAINNET } from "../../types/Network";
import { buildTzktAddressUrl } from "./helpers";
test("buildTzktUrl returns the right value for a given network", () => {
- expect(buildTzktAddressUrl(TezosNetwork.GHOSTNET, "mockAddress")).toEqual(
+ expect(buildTzktAddressUrl(GHOSTNET, "mockAddress")).toEqual(
"https://ghostnet.tzkt.io/mockAddress"
);
- expect(buildTzktAddressUrl(TezosNetwork.MAINNET, "mockAddress")).toEqual(
- "https://tzkt.io/mockAddress"
- );
+ expect(buildTzktAddressUrl(MAINNET, "mockAddress")).toEqual("https://tzkt.io/mockAddress");
});
diff --git a/src/utils/tzkt/helpers.ts b/src/utils/tzkt/helpers.ts
index 0cf7516b0..d8c0ef9fe 100644
--- a/src/utils/tzkt/helpers.ts
+++ b/src/utils/tzkt/helpers.ts
@@ -1,5 +1,4 @@
-import { TezosNetwork } from "../../types/TezosNetwork";
-import { tzktExplorer } from "../tezos/consts";
+import { Network } from "../../types/Network";
-export const buildTzktAddressUrl = (network: TezosNetwork, pkh: string) =>
- `${tzktExplorer[network]}/${pkh}`;
+export const buildTzktAddressUrl = (network: Network, pkh: string) =>
+ `${network.tzktExplorerUrl}/${pkh}`;
diff --git a/src/utils/useAssetsPolling.test.ts b/src/utils/useAssetsPolling.test.ts
index f5379fb1b..0b26226aa 100644
--- a/src/utils/useAssetsPolling.test.ts
+++ b/src/utils/useAssetsPolling.test.ts
@@ -1,11 +1,10 @@
import { AllTheProviders, renderHook, waitFor } from "../mocks/testUtils";
import { useAssetsPolling } from "./useAssetsPolling";
-import { SupportedNetworks } from "./network";
-import { tzktUrls } from "./tezos";
import { delegatesGet } from "@tzkt/sdk-api";
import store from "./redux/store";
-import { assetsActions } from "./redux/slices/assetsSlice";
import { mockBaker } from "../mocks/factories";
+import { DefaultNetworks } from "../types/Network";
+import { networksActions } from "./redux/slices/networks";
jest.unmock("./tezos");
jest.mock("@tzkt/sdk-api", () => {
@@ -15,13 +14,13 @@ jest.mock("@tzkt/sdk-api", () => {
});
describe("useAssetsPolling", () => {
- describe.each(SupportedNetworks)("network: %s", network => {
+ describe.each(DefaultNetworks)("on $name", network => {
beforeAll(() => {
- store.dispatch(assetsActions.updateNetwork(network));
+ store.dispatch(networksActions.setCurrent(network));
});
test("bakers", async () => {
- const baseUrl = tzktUrls[network];
+ const baseUrl = network.tzktApiUrl;
(delegatesGet as jest.Mock).mockResolvedValue([
{ ...mockBaker(0), alias: mockBaker(0).name },
{ ...mockBaker(1), alias: mockBaker(1).name },
diff --git a/src/utils/useAssetsPolling.ts b/src/utils/useAssetsPolling.ts
index b07f29218..3f4f77f25 100644
--- a/src/utils/useAssetsPolling.ts
+++ b/src/utils/useAssetsPolling.ts
@@ -1,10 +1,10 @@
import { chunk, compact } from "lodash";
import { useEffect, useRef } from "react";
import { useQuery, useQueryClient } from "react-query";
-import { TezosNetwork } from "../types/TezosNetwork";
+import { Network } from "../types/Network";
import { TokenTransfer } from "../types/Transfer";
import { useImplicitAccounts } from "./hooks/accountHooks";
-import { useRefetchTrigger, useSelectedNetwork } from "./hooks/assetsHooks";
+import { useRefetchTrigger } from "./hooks/assetsHooks";
import { getPendingOperationsForMultisigs, getRelevantMultisigContracts } from "./multisig/helpers";
import { processInBatches } from "./promise";
import {
@@ -28,17 +28,18 @@ import {
} from "./tezos";
import errorsSlice from "./redux/slices/errorsSlice";
import getErrorContext from "./getErrorContext";
+import { useSelectedNetwork } from "./hooks/networkHooks";
const getTezTransfersPayload = async (
pkh: string,
- network: TezosNetwork
+ network: Network
): Promise => {
const transfers = await getTezTransfers(pkh, network);
return { pkh, transfers };
};
const getTokensTransfersPayload = async (
pkh: string,
- network: TezosNetwork
+ network: Network
): Promise => {
const transfers = await getTokenTransfers(pkh, network);
// there are no token transfers without a token & amount assigned
@@ -47,7 +48,7 @@ const getTokensTransfersPayload = async (
const getDelegationsPayload = async (
pkh: string,
- network: TezosNetwork
+ network: Network
): Promise => {
const delegation = await getLastDelegation(pkh, network);
return delegation && { pkh, delegation };
diff --git a/src/views/batch/OperationView.test.tsx b/src/views/batch/OperationView.test.tsx
index 3123546ca..b985bd10a 100644
--- a/src/views/batch/OperationView.test.tsx
+++ b/src/views/batch/OperationView.test.tsx
@@ -12,7 +12,7 @@ import { ghostnetThezard } from "../../mocks/nftTokens";
import { render, screen } from "../../mocks/testUtils";
import { parseContractPkh } from "../../types/Address";
import { FA12Transfer, FA2Transfer } from "../../types/Operation";
-import { TezosNetwork } from "../../types/TezosNetwork";
+import { MAINNET } from "../../types/Network";
import { tokensActions } from "../../utils/redux/slices/tokensSlice";
import store from "../../utils/redux/store";
import { TEZ } from "../../utils/tezos";
@@ -43,9 +43,7 @@ describe("", () => {
test("fa1.2", () => {
const token = hedgehoge(mockImplicitAddress(0));
- store.dispatch(
- tokensActions.addTokens({ network: TezosNetwork.MAINNET, tokens: [token.token] })
- );
+ store.dispatch(tokensActions.addTokens({ network: MAINNET, tokens: [token.token] }));
const operation: FA12Transfer = {
...mockFA12Operation(2),
contract: parseContractPkh(token.token.contract.address as string),
@@ -55,7 +53,7 @@ describe("", () => {
expect(screen.getByRole("heading", { name: "0.001234 Hedgehoge" })).toBeInTheDocument();
expect(screen.getByTestId("link")).toHaveAttribute(
"href",
- "https://mainnet.tzkt.io/KT1G1cCRNBgQ48mVDjopHjEmTN5Sbtar8nn9/tokens/0"
+ "https://tzkt.io/KT1G1cCRNBgQ48mVDjopHjEmTN5Sbtar8nn9/tokens/0"
);
});
@@ -63,9 +61,7 @@ describe("", () => {
const token = uUSD(mockImplicitAddress(0));
token.token.standard = "fa2";
token.token.tokenId = "5";
- store.dispatch(
- tokensActions.addTokens({ network: TezosNetwork.MAINNET, tokens: [token.token] })
- );
+ store.dispatch(tokensActions.addTokens({ network: MAINNET, tokens: [token.token] }));
const operation: FA2Transfer = {
...mockFA2Operation(2),
contract: parseContractPkh(token.token.contract.address as string),
@@ -78,7 +74,7 @@ describe("", () => {
).toBeInTheDocument();
expect(screen.getByTestId("link")).toHaveAttribute(
"href",
- "https://mainnet.tzkt.io/KT1QTcAXeefhJ3iXLurRt81WRKdv7YqyYFmo/tokens/5"
+ "https://tzkt.io/KT1QTcAXeefhJ3iXLurRt81WRKdv7YqyYFmo/tokens/5"
);
});
@@ -86,9 +82,7 @@ describe("", () => {
const token = ghostnetThezard;
token.token.standard = "fa2";
token.token.tokenId = "15";
- store.dispatch(
- tokensActions.addTokens({ network: TezosNetwork.MAINNET, tokens: [token.token] })
- );
+ store.dispatch(tokensActions.addTokens({ network: MAINNET, tokens: [token.token] }));
const operation: FA2Transfer = {
...mockFA2Operation(2),
contract: parseContractPkh(token.token.contract.address as string),
@@ -101,7 +95,7 @@ describe("", () => {
expect(screen.getByTestId("link")).toHaveAttribute(
"href",
- "https://mainnet.tzkt.io/KT1GVhG7dQNjPAt4FNBNmc9P9zpiQex4Mxob/tokens/15"
+ "https://tzkt.io/KT1GVhG7dQNjPAt4FNBNmc9P9zpiQex4Mxob/tokens/15"
);
});
});
diff --git a/src/views/batch/OperationView.tsx b/src/views/batch/OperationView.tsx
index 886a53a9e..fa9fb0fcb 100644
--- a/src/views/batch/OperationView.tsx
+++ b/src/views/batch/OperationView.tsx
@@ -1,12 +1,12 @@
import { AspectRatio, Flex, Heading, Image, Link, Tooltip } from "@chakra-ui/react";
import { Operation } from "../../types/Operation";
-import { useSelectedNetwork } from "../../utils/hooks/assetsHooks";
import { useGetToken } from "../../utils/hooks/tokensHooks";
import { prettyTezAmount } from "../../utils/format";
import colors from "../../style/colors";
import { getIPFSurl } from "../../utils/token/nftUtils";
import { thumbnailUri, tokenNameSafe, tokenUri } from "../../types/Token";
import { tokenTitle } from "./BatchView";
+import { useSelectedNetwork } from "../../utils/hooks/networkHooks";
export const OperationView = ({ operation }: { operation: Operation }) => {
const getToken = useGetToken();
diff --git a/src/views/nfts/NFTsView.test.tsx b/src/views/nfts/NFTsView.test.tsx
index 5641794d8..535e86087 100644
--- a/src/views/nfts/NFTsView.test.tsx
+++ b/src/views/nfts/NFTsView.test.tsx
@@ -5,11 +5,12 @@ import { ReduxStore } from "../../providers/ReduxStore";
import store from "../../utils/redux/store";
import tokensSlice from "../../utils/redux/slices/tokensSlice";
import NFTsViewBase from "./NftsView";
-import { TezosNetwork } from "../../types/TezosNetwork";
import assetsSlice from "../../utils/redux/slices/assetsSlice";
import accountsSlice from "../../utils/redux/slices/accountsSlice";
+import { MAINNET } from "../../types/Network";
+import { networksActions } from "../../utils/redux/slices/networks";
-const { updateTokenBalance, updateNetwork } = assetsSlice.actions;
+const { updateTokenBalance } = assetsSlice.actions;
beforeEach(() => {
store.dispatch(accountsSlice.actions.addAccount([mockImplicitAccount(0)]));
@@ -33,7 +34,7 @@ describe("NFTsView", () => {
store.dispatch(
accountsSlice.actions.addAccount([mockImplicitAccount(1), mockImplicitAccount(2)])
);
- store.dispatch(updateNetwork(TezosNetwork.MAINNET));
+ store.dispatch(networksActions.setCurrent(MAINNET));
store.dispatch(
updateTokenBalance([
mockNFTToken(1, mockImplicitAccount(1).address.pkh),
@@ -44,7 +45,7 @@ describe("NFTsView", () => {
);
store.dispatch(
tokensSlice.actions.addTokens({
- network: TezosNetwork.MAINNET,
+ network: MAINNET,
tokens: [
mockNFTToken(1, mockImplicitAddress(1).pkh).token,
mockNFTToken(2, mockImplicitAddress(1).pkh).token,
diff --git a/src/views/nfts/drawer/PropertiesAccordionItem.test.tsx b/src/views/nfts/drawer/PropertiesAccordionItem.test.tsx
index 9c2f621fe..bc5abd2a2 100644
--- a/src/views/nfts/drawer/PropertiesAccordionItem.test.tsx
+++ b/src/views/nfts/drawer/PropertiesAccordionItem.test.tsx
@@ -84,7 +84,7 @@ describe("PropertiesAccordionItem", () => {
delete nft.metadata.creators;
render(fixture(nft));
- // act(() => store.dispatch(assetsActions.updateNetwork(TezosNetwork.MAINNET)));
+ // act(() => store.dispatch(networksActions.setCurrent("mainnet")));
expect(screen.getByTestId("nft-creator")).toHaveTextContent("Creator:");
expect(screen.queryByTestId("nft-creator-value")).toHaveTextContent("-");
});
diff --git a/src/views/nfts/drawer/PropertiesAccordionItem.tsx b/src/views/nfts/drawer/PropertiesAccordionItem.tsx
index 0ed1ccf0f..5f465645b 100644
--- a/src/views/nfts/drawer/PropertiesAccordionItem.tsx
+++ b/src/views/nfts/drawer/PropertiesAccordionItem.tsx
@@ -16,8 +16,8 @@ import { TruncatedTextWithTooltip } from "../../../components/TruncatedTextWithT
import { TzktLink } from "../../../components/TzktLink";
import { parsePkh } from "../../../types/Address";
import { metadataUri, mimeType, royalties } from "../../../types/Token";
-import { useSelectedNetwork } from "../../../utils/hooks/assetsHooks";
import { NFTBalance } from "../../../types/TokenBalance";
+import { useSelectedNetwork } from "../../../utils/hooks/networkHooks";
const CreatorElement = ({ nft }: { nft: NFTBalance }) => {
if (!nft.metadata.creators || nft.metadata.creators.length === 0) {
diff --git a/src/views/operations/operationUtils.test.ts b/src/views/operations/operationUtils.test.ts
index c8cbbe2a8..163d29a13 100644
--- a/src/views/operations/operationUtils.test.ts
+++ b/src/views/operations/operationUtils.test.ts
@@ -7,468 +7,179 @@ import {
rawTzktNftTransfer,
} from "../../mocks/tzktResponse";
import { OperationDisplay, TezTransfer, TokenTransfer } from "../../types/Transfer";
-import { SupportedNetworks } from "../../utils/network";
import {
getOperationDisplays,
getTezOperationDisplay,
getTokenOperationDisplay,
getTransactionUrl,
} from "./operationsUtils";
+import { DefaultNetworks } from "../../types/Network";
const forAddress = "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS";
-describe("getTezOperationDisplay", () => {
- test("it throws for a tez transfer non related to reference address", () => {
- const incomingTez: TezTransfer = {
- type: "transaction",
- id: 109783351820288,
- level: 2213611,
- timestamp: "2023-03-27T08:47:30Z",
- block: "BM4xPHaLWYYw2KLwQrpUYjMYf1eN1mqfjtCEYUCgFpuyAd6u5cH",
- hash: "ooZCfnsMgXvxni6umn999MKfpT6zmVJpDzZmmCCh6AZ89gvUHGM",
- counter: 134162,
- sender: { address: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3" },
- gasLimit: 1101,
- gasUsed: 1001,
- storageLimit: 0,
- storageUsed: 0,
- bakerFee: 402,
- storageFee: 0,
- allocationFee: 0,
- target: { address: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
- amount: 2400000,
- status: "applied",
- hasInternals: false,
- };
-
- expect(() => getTezOperationDisplay(incomingTez, mockImplicitAddress(4).pkh)).toThrowError(
- "Address tz1i9imTXjMAW5HP5g3wq55Pcr43tDz8c3VZ doesn't match sender or recipient"
- );
- });
-
- test("returns null for a token transfer non related to reference address", () => {
- const incomingKL3: TokenTransfer = {
- id: 109855493849090,
- level: 2215193,
- timestamp: "2023-03-27T13:29:22Z",
- token: {
- id: 10898231001089,
- contract: {
- address: "KT1XZoJ3PAidWVWRiKWESmPj64eKN7CEHuWZ",
- },
- tokenId: "1",
- standard: "fa2",
- totalSupply: "13000000000",
- metadata: {
- name: "Klondike3",
- symbol: "KL3",
- decimals: "5",
- },
- },
- from: {
- address: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS",
- },
- to: {
- address: "tz1ikfEcj3LmsmxpcC1RMZNzBHbEmybCc43D",
- },
- amount: "451000",
- transactionId: 109855493849088,
- };
-
- expect(() => getTokenOperationDisplay(incomingKL3, mockImplicitAddress(4).pkh)).toThrowError(
- "Address tz1i9imTXjMAW5HP5g3wq55Pcr43tDz8c3VZ doesn't match sender or recipient"
- );
- });
-
- test("case tez incoming", () => {
- const incomingTez: TezTransfer = {
- type: "transaction",
- id: 109783351820288,
- level: 2213611,
- timestamp: "2023-03-27T08:47:30Z",
- block: "BM4xPHaLWYYw2KLwQrpUYjMYf1eN1mqfjtCEYUCgFpuyAd6u5cH",
- hash: "ooZCfnsMgXvxni6umn999MKfpT6zmVJpDzZmmCCh6AZ89gvUHGM",
- counter: 134162,
- sender: { address: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3" },
- gasLimit: 1101,
- gasUsed: 1001,
- storageLimit: 0,
- storageUsed: 0,
- bakerFee: 402,
- storageFee: 0,
- allocationFee: 0,
- target: { address: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
- amount: 2400000,
- status: "applied",
- hasInternals: false,
- };
-
- const result = getTezOperationDisplay(incomingTez, forAddress);
-
- const expected: OperationDisplay = {
- id: 109783351820288,
- amount: { prettyDisplay: "+2.400000 ꜩ" },
- fee: "0.000402 ꜩ",
- prettyTimestamp: "today at 10:47 AM",
- recipient: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
- sender: { type: "implicit", pkh: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3" },
- status: "confirmed",
- timestamp: "2023-03-27T08:47:30Z",
- type: "transaction",
- tzktUrl: "https://mainnet.tzkt.io/ooZCfnsMgXvxni6umn999MKfpT6zmVJpDzZmmCCh6AZ89gvUHGM",
- level: 2213611,
- };
- expect(result).toEqual(expected);
- });
-
- test("case tez outgoing", () => {
- const outgoingTez: TezTransfer = {
- type: "transaction",
- id: 109810172297216,
- level: 2214204,
- timestamp: "2023-03-27T10:36:40Z",
- block: "BKyZ7dksWdf6sFcnWnwvS5FgQ8JgEMFxg3SsL1bWR3FBz5mSAX3",
- hash: "oo3Moa2XToLeCjiVhQFHWe3aJkFtqbbW2GKvG9Zvb5aZLs6tHWZ",
- counter: 10304021,
- sender: {
- address: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS",
- },
- gasLimit: 1101,
- gasUsed: 1001,
- storageLimit: 0,
- storageUsed: 0,
- bakerFee: 403,
- storageFee: 0,
- allocationFee: 0,
- target: {
- address: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3",
- },
- amount: 6410000,
- status: "applied",
- hasInternals: false,
- };
-
- const result = getTezOperationDisplay(outgoingTez, forAddress);
-
- const expected: OperationDisplay = {
- id: 109810172297216,
- amount: { prettyDisplay: "-6.410000 ꜩ" },
- fee: "0.000403 ꜩ",
- prettyTimestamp: "today at 12:36 PM",
- recipient: { type: "implicit", pkh: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3" },
- sender: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
- status: "confirmed",
- timestamp: "2023-03-27T10:36:40Z",
- type: "transaction",
- tzktUrl: "https://mainnet.tzkt.io/oo3Moa2XToLeCjiVhQFHWe3aJkFtqbbW2GKvG9Zvb5aZLs6tHWZ",
- level: 2214204,
- };
-
- expect(result).toEqual(expected);
- });
-
- test("incoming nft", () => {
- const incomingNft: TokenTransfer = rawTzktNftTransfer;
-
- const result = getTokenOperationDisplay(incomingNft, forAddress);
-
- const expected = {
- id: 109817445220353,
- type: "transaction",
- tzktUrl: "https://mainnet.tzkt.io/transactions/109817445220352",
- amount: {
- id: 10899580518401,
- prettyDisplay: "+1",
- url: "https://ipfs.io/ipfs/zb2rhfbacgmTnG13DiCvjs6J21hzMeAueYVWg37C5owThnpfQ",
- },
- prettyTimestamp: "today at 1:06 PM",
- recipient: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
- sender: { type: "implicit", pkh: "tz1W5iRhKWPoLviqExtDDKJqCcPRLBWMhg6S" },
- timestamp: "2023-03-27T11:06:40Z",
- level: 2214369,
- };
-
- expect(result).toEqual(expected);
- });
-
- test("incoming nft with missing from", () => {
- const incomingNft = { ...rawTzktNftTransfer, from: undefined };
-
- const result = getTokenOperationDisplay(incomingNft, forAddress);
-
- const expected = {
- id: 109817445220353,
- type: "transaction",
- tzktUrl: "https://mainnet.tzkt.io/transactions/109817445220352",
- amount: {
- id: 10899580518401,
- prettyDisplay: "+1",
- url: "https://ipfs.io/ipfs/zb2rhfbacgmTnG13DiCvjs6J21hzMeAueYVWg37C5owThnpfQ",
- },
- prettyTimestamp: "today at 1:06 PM",
- recipient: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
- sender: { type: "contract", pkh: "KT1GVhG7dQNjPAt4FNBNmc9P9zpiQex4Mxob" },
- timestamp: "2023-03-27T11:06:40Z",
- level: 2214369,
- };
-
- expect(result).toEqual(expected);
- });
-
- test("outgoing Nft", () => {
- const outgoingNft = {
- ...rawTzktNftTransfer,
- from: {
- address: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS",
- },
- to: {
- address: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3",
- },
- };
-
- const expected = {
- id: 109817445220353,
- type: "transaction",
- amount: {
- id: 10899580518401,
- prettyDisplay: "-1",
- url: "https://ipfs.io/ipfs/zb2rhfbacgmTnG13DiCvjs6J21hzMeAueYVWg37C5owThnpfQ",
- },
- tzktUrl: "https://mainnet.tzkt.io/transactions/109817445220352",
- prettyTimestamp: "today at 1:06 PM",
- recipient: { type: "implicit", pkh: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3" },
- sender: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
- timestamp: "2023-03-27T11:06:40Z",
- level: 2214369,
- };
-
- const result = getTokenOperationDisplay(outgoingNft, forAddress);
- expect(result).toEqual(expected);
- });
-
- test("Incoming fa2 token", () => {
- const incomingKL3: TokenTransfer = {
- id: 109855131041793,
- level: 2215185,
- timestamp: "2023-03-27T13:27:13Z",
- token: {
- id: 10898231001089,
- contract: {
- address: "KT1XZoJ3PAidWVWRiKWESmPj64eKN7CEHuWZ",
- },
- tokenId: "1",
- standard: "fa2",
- totalSupply: "13000000000",
- metadata: {
- name: "Klondike3",
- symbol: "KL3",
- decimals: "5",
- },
- },
- from: {
- address: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3",
- },
- to: {
- address: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS",
- },
- amount: "716850",
- transactionId: 109855131041792,
- };
-
- const result = getTokenOperationDisplay(incomingKL3, forAddress);
- const expected = {
- id: 109855131041793,
- type: "transaction",
- tzktUrl: "https://mainnet.tzkt.io/transactions/109855131041792",
- amount: {
- id: 10898231001089,
- prettyDisplay: "+7.16850 KL3",
- url: undefined,
- },
- prettyTimestamp: "today at 3:27 PM",
- recipient: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
- sender: { type: "implicit", pkh: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3" },
- timestamp: "2023-03-27T13:27:13Z",
- level: 2215185,
- };
- expect(result).toEqual(expected);
- });
-
- test("Outgoing fa2 token", () => {
- const incomingKL3: TokenTransfer = {
- id: 109855493849090,
- level: 2215193,
- timestamp: "2023-03-27T13:29:22Z",
- token: {
- id: 10898231001089,
- contract: {
- address: "KT1XZoJ3PAidWVWRiKWESmPj64eKN7CEHuWZ",
- },
- tokenId: "1",
- standard: "fa2",
- totalSupply: "13000000000",
- metadata: {
- name: "Klondike3",
- symbol: "KL3",
- decimals: "5",
- },
- },
- from: {
- address: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS",
- },
- to: {
- address: "tz1ikfEcj3LmsmxpcC1RMZNzBHbEmybCc43D",
- },
- amount: "451000",
- transactionId: 109855493849088,
- };
-
- const result = getTokenOperationDisplay(incomingKL3, forAddress);
- const expected = {
- id: 109855493849090,
- type: "transaction",
- tzktUrl: "https://mainnet.tzkt.io/transactions/109855493849088",
- amount: {
- id: 10898231001089,
- prettyDisplay: "-4.51000 KL3",
- url: undefined,
- },
- prettyTimestamp: "today at 3:29 PM",
- recipient: { type: "implicit", pkh: "tz1ikfEcj3LmsmxpcC1RMZNzBHbEmybCc43D" },
- sender: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
- timestamp: "2023-03-27T13:29:22Z",
- level: 2215193,
- };
- expect(result).toEqual(expected);
- });
+describe.each(DefaultNetworks)("on $name", network => {
+ describe("getTezOperationDisplay", () => {
+ test("it throws for a tez transfer non related to reference address", () => {
+ const incomingTez: TezTransfer = {
+ type: "transaction",
+ id: 109783351820288,
+ level: 2213611,
+ timestamp: "2023-03-27T08:47:30Z",
+ block: "BM4xPHaLWYYw2KLwQrpUYjMYf1eN1mqfjtCEYUCgFpuyAd6u5cH",
+ hash: "ooZCfnsMgXvxni6umn999MKfpT6zmVJpDzZmmCCh6AZ89gvUHGM",
+ counter: 134162,
+ sender: { address: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3" },
+ gasLimit: 1101,
+ gasUsed: 1001,
+ storageLimit: 0,
+ storageUsed: 0,
+ bakerFee: 402,
+ storageFee: 0,
+ allocationFee: 0,
+ target: { address: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
+ amount: 2400000,
+ status: "applied",
+ hasInternals: false,
+ };
- test("Incoming fa1.2 token", () => {
- const incomingFa12: TokenTransfer = {
- id: 109855847219201,
- level: 2215201,
- timestamp: "2023-03-27T13:30:37Z",
- token: {
- id: 10897625972737,
- contract: {
- address: "KT1UCPcXExqEYRnfoXWYvBkkn5uPjn8TBTEe",
- },
- tokenId: "0",
- standard: "fa1.2",
- totalSupply: "13000000",
- },
- from: {
- address: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3",
- },
- to: {
- address: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS",
- },
- amount: "27400",
- transactionId: 109855847219200,
- };
-
- const result = getTokenOperationDisplay(incomingFa12, forAddress);
- const expected = {
- id: 109855847219201,
- type: "transaction",
- tzktUrl: "https://mainnet.tzkt.io/transactions/109855847219200",
- amount: {
- id: 10897625972737,
- prettyDisplay: "+27,400 FA1.2",
- url: undefined,
- },
- prettyTimestamp: "today at 3:30 PM",
- recipient: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
- sender: { type: "implicit", pkh: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3" },
- timestamp: "2023-03-27T13:30:37Z",
- level: 2215201,
- };
- expect(result).toEqual(expected);
- });
-});
+ expect(() =>
+ getTezOperationDisplay(incomingTez, mockImplicitAddress(4).pkh, network)
+ ).toThrowError(
+ "Address tz1i9imTXjMAW5HP5g3wq55Pcr43tDz8c3VZ doesn't match sender or recipient"
+ );
+ });
-describe("getOperationDisplays", () => {
- it("returns the right value", () => {
- const result = getOperationDisplays(
- getTransactionsResult,
- getTokenTransactionsResult,
- getLatestDelegationResult,
- forAddress
- );
-
- const expected: OperationDisplay[] = [
- {
- id: 537704232124416,
- amount: { prettyDisplay: "0.467532 ꜩ" },
- fee: "0.000396 ꜩ",
- level: 3414723,
- prettyTimestamp: "04/24/2023",
- recipient: { type: "implicit", pkh: "tz1fHn9ZSqMwp1WNwdCLqnh52yPgzQ4QydTm" },
- sender: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
- timestamp: "2023-04-24T09:48:17Z",
- type: "delegation",
- tzktUrl: "https://mainnet.tzkt.io/onxgPmNMo4756y7PhXeYethMVf2e3HUSHoZuia8rY5qFujgbqva",
- },
- {
- id: 109855847219201,
- amount: {
- id: 10897625972737,
- prettyDisplay: "+27,400 FA1.2",
- url: undefined,
- },
- prettyTimestamp: "today at 3:30 PM",
- recipient: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
- sender: { type: "implicit", pkh: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3" },
- timestamp: "2023-03-27T13:30:37Z",
- type: "transaction",
- tzktUrl: "https://mainnet.tzkt.io/transactions/109855847219200",
- level: 2215201,
- },
- {
+ test("returns null for a token transfer non related to reference address", () => {
+ const incomingKL3: TokenTransfer = {
id: 109855493849090,
- amount: {
- id: 10898231001089,
- prettyDisplay: "-4.51000 KL3",
- url: undefined,
- },
- prettyTimestamp: "today at 3:29 PM",
- recipient: { type: "implicit", pkh: "tz1ikfEcj3LmsmxpcC1RMZNzBHbEmybCc43D" },
- sender: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
- timestamp: "2023-03-27T13:29:22Z",
- type: "transaction",
- tzktUrl: "https://mainnet.tzkt.io/transactions/109855493849088",
level: 2215193,
- },
- {
- id: 109855131041793,
- amount: {
+ timestamp: "2023-03-27T13:29:22Z",
+ token: {
id: 10898231001089,
- prettyDisplay: "+7.16850 KL3",
- url: undefined,
+ contract: {
+ address: "KT1XZoJ3PAidWVWRiKWESmPj64eKN7CEHuWZ",
+ },
+ tokenId: "1",
+ standard: "fa2",
+ totalSupply: "13000000000",
+ metadata: {
+ name: "Klondike3",
+ symbol: "KL3",
+ decimals: "5",
+ },
},
- prettyTimestamp: "today at 3:27 PM",
+ from: {
+ address: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS",
+ },
+ to: {
+ address: "tz1ikfEcj3LmsmxpcC1RMZNzBHbEmybCc43D",
+ },
+ amount: "451000",
+ transactionId: 109855493849088,
+ };
+
+ expect(() =>
+ getTokenOperationDisplay(incomingKL3, mockImplicitAddress(4).pkh, network)
+ ).toThrowError(
+ "Address tz1i9imTXjMAW5HP5g3wq55Pcr43tDz8c3VZ doesn't match sender or recipient"
+ );
+ });
+
+ test("case tez incoming", () => {
+ const incomingTez: TezTransfer = {
+ type: "transaction",
+ id: 109783351820288,
+ level: 2213611,
+ timestamp: "2023-03-27T08:47:30Z",
+ block: "BM4xPHaLWYYw2KLwQrpUYjMYf1eN1mqfjtCEYUCgFpuyAd6u5cH",
+ hash: "ooZCfnsMgXvxni6umn999MKfpT6zmVJpDzZmmCCh6AZ89gvUHGM",
+ counter: 134162,
+ sender: { address: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3" },
+ gasLimit: 1101,
+ gasUsed: 1001,
+ storageLimit: 0,
+ storageUsed: 0,
+ bakerFee: 402,
+ storageFee: 0,
+ allocationFee: 0,
+ target: { address: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
+ amount: 2400000,
+ status: "applied",
+ hasInternals: false,
+ };
+
+ const result = getTezOperationDisplay(incomingTez, forAddress, network);
+
+ const expected: OperationDisplay = {
+ id: 109783351820288,
+ amount: { prettyDisplay: "+2.400000 ꜩ" },
+ fee: "0.000402 ꜩ",
+ prettyTimestamp: "today at 10:47 AM",
recipient: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
sender: { type: "implicit", pkh: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3" },
- timestamp: "2023-03-27T13:27:13Z",
+ status: "confirmed",
+ timestamp: "2023-03-27T08:47:30Z",
type: "transaction",
- tzktUrl: "https://mainnet.tzkt.io/transactions/109855131041792",
- level: 2215185,
- },
- {
- id: 109854457856001,
- amount: {
- id: 10899580518401,
- prettyDisplay: "-1",
- url: "https://ipfs.io/ipfs/zb2rhfbacgmTnG13DiCvjs6J21hzMeAueYVWg37C5owThnpfQ",
+ tzktUrl: `${network.tzktExplorerUrl}/ooZCfnsMgXvxni6umn999MKfpT6zmVJpDzZmmCCh6AZ89gvUHGM`,
+ level: 2213611,
+ };
+ expect(result).toEqual(expected);
+ });
+
+ test("case tez outgoing", () => {
+ const outgoingTez: TezTransfer = {
+ type: "transaction",
+ id: 109810172297216,
+ level: 2214204,
+ timestamp: "2023-03-27T10:36:40Z",
+ block: "BKyZ7dksWdf6sFcnWnwvS5FgQ8JgEMFxg3SsL1bWR3FBz5mSAX3",
+ hash: "oo3Moa2XToLeCjiVhQFHWe3aJkFtqbbW2GKvG9Zvb5aZLs6tHWZ",
+ counter: 10304021,
+ sender: {
+ address: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS",
},
- prettyTimestamp: "today at 3:24 PM",
+ gasLimit: 1101,
+ gasUsed: 1001,
+ storageLimit: 0,
+ storageUsed: 0,
+ bakerFee: 403,
+ storageFee: 0,
+ allocationFee: 0,
+ target: {
+ address: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3",
+ },
+ amount: 6410000,
+ status: "applied",
+ hasInternals: false,
+ };
+
+ const result = getTezOperationDisplay(outgoingTez, forAddress, network);
+
+ const expected: OperationDisplay = {
+ id: 109810172297216,
+ amount: { prettyDisplay: "-6.410000 ꜩ" },
+ fee: "0.000403 ꜩ",
+ prettyTimestamp: "today at 12:36 PM",
recipient: { type: "implicit", pkh: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3" },
sender: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
- timestamp: "2023-03-27T13:24:48Z",
+ status: "confirmed",
+ timestamp: "2023-03-27T10:36:40Z",
type: "transaction",
- tzktUrl: "https://mainnet.tzkt.io/transactions/109854457856000",
- level: 2215172,
- },
- {
+ tzktUrl: `${network.tzktExplorerUrl}/oo3Moa2XToLeCjiVhQFHWe3aJkFtqbbW2GKvG9Zvb5aZLs6tHWZ`,
+ level: 2214204,
+ };
+
+ expect(result).toEqual(expected);
+ });
+
+ test("incoming nft", () => {
+ const incomingNft: TokenTransfer = rawTzktNftTransfer;
+
+ const result = getTokenOperationDisplay(incomingNft, forAddress, network);
+
+ const expected = {
id: 109817445220353,
+ type: "transaction",
+ tzktUrl: `${network.tzktExplorerUrl}/transactions/109817445220352`,
amount: {
id: 10899580518401,
prettyDisplay: "+1",
@@ -478,137 +189,433 @@ describe("getOperationDisplays", () => {
recipient: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
sender: { type: "implicit", pkh: "tz1W5iRhKWPoLviqExtDDKJqCcPRLBWMhg6S" },
timestamp: "2023-03-27T11:06:40Z",
+ level: 2214369,
+ };
+
+ expect(result).toEqual(expected);
+ });
+
+ test("incoming nft with missing from", () => {
+ const incomingNft = { ...rawTzktNftTransfer, from: undefined };
+
+ const result = getTokenOperationDisplay(incomingNft, forAddress, network);
+
+ const expected = {
+ id: 109817445220353,
type: "transaction",
- tzktUrl: "https://mainnet.tzkt.io/transactions/109817445220352",
+ tzktUrl: `${network.tzktExplorerUrl}/transactions/109817445220352`,
+ amount: {
+ id: 10899580518401,
+ prettyDisplay: "+1",
+ url: "https://ipfs.io/ipfs/zb2rhfbacgmTnG13DiCvjs6J21hzMeAueYVWg37C5owThnpfQ",
+ },
+ prettyTimestamp: "today at 1:06 PM",
+ recipient: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
+ sender: { type: "contract", pkh: "KT1GVhG7dQNjPAt4FNBNmc9P9zpiQex4Mxob" },
+ timestamp: "2023-03-27T11:06:40Z",
level: 2214369,
- },
- {
- id: 109810172297216,
- amount: { prettyDisplay: "-6.410000 ꜩ" },
- fee: "0.000403 ꜩ",
- prettyTimestamp: "today at 12:36 PM",
+ };
+
+ expect(result).toEqual(expected);
+ });
+
+ test("outgoing Nft", () => {
+ const outgoingNft = {
+ ...rawTzktNftTransfer,
+ from: {
+ address: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS",
+ },
+ to: {
+ address: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3",
+ },
+ };
+
+ const expected = {
+ id: 109817445220353,
+ type: "transaction",
+ amount: {
+ id: 10899580518401,
+ prettyDisplay: "-1",
+ url: "https://ipfs.io/ipfs/zb2rhfbacgmTnG13DiCvjs6J21hzMeAueYVWg37C5owThnpfQ",
+ },
+ tzktUrl: `${network.tzktExplorerUrl}/transactions/109817445220352`,
+ prettyTimestamp: "today at 1:06 PM",
recipient: { type: "implicit", pkh: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3" },
sender: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
- status: "confirmed",
- timestamp: "2023-03-27T10:36:40Z",
- type: "transaction",
- tzktUrl: "https://mainnet.tzkt.io/oo3Moa2XToLeCjiVhQFHWe3aJkFtqbbW2GKvG9Zvb5aZLs6tHWZ",
- level: 2214204,
- },
- {
- id: 109783351820288,
- amount: { prettyDisplay: "+2.400000 ꜩ" },
- fee: "0.000402 ꜩ",
- prettyTimestamp: "today at 10:47 AM",
- recipient: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
- sender: { type: "implicit", pkh: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3" },
- status: "confirmed",
- timestamp: "2023-03-27T08:47:30Z",
+ timestamp: "2023-03-27T11:06:40Z",
+ level: 2214369,
+ };
+
+ const result = getTokenOperationDisplay(outgoingNft, forAddress, network);
+ expect(result).toEqual(expected);
+ });
+
+ test("Incoming fa2 token", () => {
+ const incomingKL3: TokenTransfer = {
+ id: 109855131041793,
+ level: 2215185,
+ timestamp: "2023-03-27T13:27:13Z",
+ token: {
+ id: 10898231001089,
+ contract: {
+ address: "KT1XZoJ3PAidWVWRiKWESmPj64eKN7CEHuWZ",
+ },
+ tokenId: "1",
+ standard: "fa2",
+ totalSupply: "13000000000",
+ metadata: {
+ name: "Klondike3",
+ symbol: "KL3",
+ decimals: "5",
+ },
+ },
+ from: {
+ address: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3",
+ },
+ to: {
+ address: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS",
+ },
+ amount: "716850",
+ transactionId: 109855131041792,
+ };
+
+ const result = getTokenOperationDisplay(incomingKL3, forAddress, network);
+ const expected = {
+ id: 109855131041793,
type: "transaction",
- tzktUrl: "https://mainnet.tzkt.io/ooZCfnsMgXvxni6umn999MKfpT6zmVJpDzZmmCCh6AZ89gvUHGM",
- level: 2213611,
- },
- {
- id: 109511935262721,
+ tzktUrl: `${network.tzktExplorerUrl}/transactions/109855131041792`,
amount: {
- id: 10898194300929,
- prettyDisplay: "+2.10000 KL2",
+ id: 10898231001089,
+ prettyDisplay: "+7.16850 KL3",
url: undefined,
},
- prettyTimestamp: "yesterday at 4:38 PM",
+ prettyTimestamp: "today at 3:27 PM",
recipient: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
- sender: { type: "implicit", pkh: "tz1ikfEcj3LmsmxpcC1RMZNzBHbEmybCc43D" },
- timestamp: "2023-03-26T14:38:48Z",
- type: "transaction",
- tzktUrl: "https://mainnet.tzkt.io/transactions/109511935262720",
- level: 2207656,
- },
- {
- id: 109510819577856,
- amount: { prettyDisplay: "-0.000000 ꜩ" },
- fee: "0.000771 ꜩ",
- prettyTimestamp: "yesterday at 4:34 PM",
- recipient: { type: "contract", pkh: "KT1GVhG7dQNjPAt4FNBNmc9P9zpiQex4Mxob" },
- sender: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
- status: "confirmed",
- timestamp: "2023-03-26T14:34:47Z",
+ sender: { type: "implicit", pkh: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3" },
+ timestamp: "2023-03-27T13:27:13Z",
+ level: 2215185,
+ };
+ expect(result).toEqual(expected);
+ });
+
+ test("Outgoing fa2 token", () => {
+ const incomingKL3: TokenTransfer = {
+ id: 109855493849090,
+ level: 2215193,
+ timestamp: "2023-03-27T13:29:22Z",
+ token: {
+ id: 10898231001089,
+ contract: {
+ address: "KT1XZoJ3PAidWVWRiKWESmPj64eKN7CEHuWZ",
+ },
+ tokenId: "1",
+ standard: "fa2",
+ totalSupply: "13000000000",
+ metadata: {
+ name: "Klondike3",
+ symbol: "KL3",
+ decimals: "5",
+ },
+ },
+ from: {
+ address: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS",
+ },
+ to: {
+ address: "tz1ikfEcj3LmsmxpcC1RMZNzBHbEmybCc43D",
+ },
+ amount: "451000",
+ transactionId: 109855493849088,
+ };
+
+ const result = getTokenOperationDisplay(incomingKL3, forAddress, network);
+ const expected = {
+ id: 109855493849090,
type: "transaction",
- tzktUrl: "https://mainnet.tzkt.io/op9pGAxiJtPcv37KRnLWhYBDx2RRhTiBeTZNsKQAQ1Pxn8AsbUC",
- level: 2207631,
- },
- {
- id: 109510819577858,
+ tzktUrl: `${network.tzktExplorerUrl}/transactions/109855493849088`,
amount: {
- id: 10899580518401,
- prettyDisplay: "-1",
- url: "https://ipfs.io/ipfs/zb2rhfbacgmTnG13DiCvjs6J21hzMeAueYVWg37C5owThnpfQ",
+ id: 10898231001089,
+ prettyDisplay: "-4.51000 KL3",
+ url: undefined,
},
- prettyTimestamp: "yesterday at 4:34 PM",
+ prettyTimestamp: "today at 3:29 PM",
recipient: { type: "implicit", pkh: "tz1ikfEcj3LmsmxpcC1RMZNzBHbEmybCc43D" },
sender: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
- timestamp: "2023-03-26T14:34:47Z",
+ timestamp: "2023-03-27T13:29:22Z",
+ level: 2215193,
+ };
+ expect(result).toEqual(expected);
+ });
+
+ test("Incoming fa1.2 token", () => {
+ const incomingFa12: TokenTransfer = {
+ id: 109855847219201,
+ level: 2215201,
+ timestamp: "2023-03-27T13:30:37Z",
+ token: {
+ id: 10897625972737,
+ contract: {
+ address: "KT1UCPcXExqEYRnfoXWYvBkkn5uPjn8TBTEe",
+ },
+ tokenId: "0",
+ standard: "fa1.2",
+ totalSupply: "13000000",
+ },
+ from: {
+ address: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3",
+ },
+ to: {
+ address: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS",
+ },
+ amount: "27400",
+ transactionId: 109855847219200,
+ };
+
+ const result = getTokenOperationDisplay(incomingFa12, forAddress, network);
+ const expected = {
+ id: 109855847219201,
type: "transaction",
- tzktUrl: "https://mainnet.tzkt.io/transactions/109510819577856",
- level: 2207631,
- },
- ];
- expect(result).toEqual(expected);
+ tzktUrl: `${network.tzktExplorerUrl}/transactions/109855847219200`,
+ amount: {
+ id: 10897625972737,
+ prettyDisplay: "+27,400 FA1.2",
+ url: undefined,
+ },
+ prettyTimestamp: "today at 3:30 PM",
+ recipient: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
+ sender: { type: "implicit", pkh: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3" },
+ timestamp: "2023-03-27T13:30:37Z",
+ level: 2215201,
+ };
+ expect(result).toEqual(expected);
+ });
});
- it("includes an active delegation", () => {
- const result = getOperationDisplays(
- [],
- [],
- {
- id: 12345,
- sender: { address: mockImplicitAddress(1).pkh },
- newDelegate: { address: mockImplicitAddress(1).pkh },
- timestamp: new Date().toISOString(),
- amount: 100000,
- hash: "mockHash",
- level: 300,
- bakerFee: 400,
- } as DelegationOperation,
- mockImplicitAddress(1).pkh
- );
- expect(result).toEqual([
- {
- id: 12345,
- amount: { prettyDisplay: "0.100000 ꜩ" },
- fee: "0.000400 ꜩ",
- level: 300,
- prettyTimestamp: "today at 4:15 PM",
- recipient: { type: "implicit", pkh: "tz1UZFB9kGauB6F5c2gfJo4hVcvrD8MeJ3Vf" },
- sender: { type: "implicit", pkh: "tz1UZFB9kGauB6F5c2gfJo4hVcvrD8MeJ3Vf" },
- timestamp: "2023-03-27T14:15:09.760Z",
- type: "delegation",
- tzktUrl: "https://mainnet.tzkt.io/mockHash",
- },
- ]);
- });
+ describe("getOperationDisplays", () => {
+ it("returns the right value", () => {
+ const result = getOperationDisplays(
+ getTransactionsResult,
+ getTokenTransactionsResult,
+ getLatestDelegationResult,
+ forAddress,
+ network
+ );
+
+ const expected: OperationDisplay[] = [
+ {
+ id: 537704232124416,
+ amount: { prettyDisplay: "0.467532 ꜩ" },
+ fee: "0.000396 ꜩ",
+ level: 3414723,
+ prettyTimestamp: "04/24/2023",
+ recipient: { type: "implicit", pkh: "tz1fHn9ZSqMwp1WNwdCLqnh52yPgzQ4QydTm" },
+ sender: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
+ timestamp: "2023-04-24T09:48:17Z",
+ type: "delegation",
+ tzktUrl: `${network.tzktExplorerUrl}/onxgPmNMo4756y7PhXeYethMVf2e3HUSHoZuia8rY5qFujgbqva`,
+ },
+ {
+ id: 109855847219201,
+ amount: {
+ id: 10897625972737,
+ prettyDisplay: "+27,400 FA1.2",
+ url: undefined,
+ },
+ prettyTimestamp: "today at 3:30 PM",
+ recipient: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
+ sender: { type: "implicit", pkh: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3" },
+ timestamp: "2023-03-27T13:30:37Z",
+ type: "transaction",
+ tzktUrl: `${network.tzktExplorerUrl}/transactions/109855847219200`,
+ level: 2215201,
+ },
+ {
+ id: 109855493849090,
+ amount: {
+ id: 10898231001089,
+ prettyDisplay: "-4.51000 KL3",
+ url: undefined,
+ },
+ prettyTimestamp: "today at 3:29 PM",
+ recipient: { type: "implicit", pkh: "tz1ikfEcj3LmsmxpcC1RMZNzBHbEmybCc43D" },
+ sender: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
+ timestamp: "2023-03-27T13:29:22Z",
+ type: "transaction",
+ tzktUrl: `${network.tzktExplorerUrl}/transactions/109855493849088`,
+ level: 2215193,
+ },
+ {
+ id: 109855131041793,
+ amount: {
+ id: 10898231001089,
+ prettyDisplay: "+7.16850 KL3",
+ url: undefined,
+ },
+ prettyTimestamp: "today at 3:27 PM",
+ recipient: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
+ sender: { type: "implicit", pkh: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3" },
+ timestamp: "2023-03-27T13:27:13Z",
+ type: "transaction",
+ tzktUrl: `${network.tzktExplorerUrl}/transactions/109855131041792`,
+ level: 2215185,
+ },
+ {
+ id: 109854457856001,
+ amount: {
+ id: 10899580518401,
+ prettyDisplay: "-1",
+ url: "https://ipfs.io/ipfs/zb2rhfbacgmTnG13DiCvjs6J21hzMeAueYVWg37C5owThnpfQ",
+ },
+ prettyTimestamp: "today at 3:24 PM",
+ recipient: { type: "implicit", pkh: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3" },
+ sender: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
+ timestamp: "2023-03-27T13:24:48Z",
+ type: "transaction",
+ tzktUrl: `${network.tzktExplorerUrl}/transactions/109854457856000`,
+ level: 2215172,
+ },
+ {
+ id: 109817445220353,
+ amount: {
+ id: 10899580518401,
+ prettyDisplay: "+1",
+ url: "https://ipfs.io/ipfs/zb2rhfbacgmTnG13DiCvjs6J21hzMeAueYVWg37C5owThnpfQ",
+ },
+ prettyTimestamp: "today at 1:06 PM",
+ recipient: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
+ sender: { type: "implicit", pkh: "tz1W5iRhKWPoLviqExtDDKJqCcPRLBWMhg6S" },
+ timestamp: "2023-03-27T11:06:40Z",
+ type: "transaction",
+ tzktUrl: `${network.tzktExplorerUrl}/transactions/109817445220352`,
+ level: 2214369,
+ },
+ {
+ id: 109810172297216,
+ amount: { prettyDisplay: "-6.410000 ꜩ" },
+ fee: "0.000403 ꜩ",
+ prettyTimestamp: "today at 12:36 PM",
+ recipient: { type: "implicit", pkh: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3" },
+ sender: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
+ status: "confirmed",
+ timestamp: "2023-03-27T10:36:40Z",
+ type: "transaction",
+ tzktUrl: `${network.tzktExplorerUrl}/oo3Moa2XToLeCjiVhQFHWe3aJkFtqbbW2GKvG9Zvb5aZLs6tHWZ`,
+ level: 2214204,
+ },
+ {
+ id: 109783351820288,
+ amount: { prettyDisplay: "+2.400000 ꜩ" },
+ fee: "0.000402 ꜩ",
+ prettyTimestamp: "today at 10:47 AM",
+ recipient: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
+ sender: { type: "implicit", pkh: "tz1UNer1ijeE9ndjzSszRduR3CzX49hoBUB3" },
+ status: "confirmed",
+ timestamp: "2023-03-27T08:47:30Z",
+ type: "transaction",
+ tzktUrl: `${network.tzktExplorerUrl}/ooZCfnsMgXvxni6umn999MKfpT6zmVJpDzZmmCCh6AZ89gvUHGM`,
+ level: 2213611,
+ },
+ {
+ id: 109511935262721,
+ amount: {
+ id: 10898194300929,
+ prettyDisplay: "+2.10000 KL2",
+ url: undefined,
+ },
+ prettyTimestamp: "yesterday at 4:38 PM",
+ recipient: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
+ sender: { type: "implicit", pkh: "tz1ikfEcj3LmsmxpcC1RMZNzBHbEmybCc43D" },
+ timestamp: "2023-03-26T14:38:48Z",
+ type: "transaction",
+ tzktUrl: `${network.tzktExplorerUrl}/transactions/109511935262720`,
+ level: 2207656,
+ },
+ {
+ id: 109510819577856,
+ amount: { prettyDisplay: "-0.000000 ꜩ" },
+ fee: "0.000771 ꜩ",
+ prettyTimestamp: "yesterday at 4:34 PM",
+ recipient: { type: "contract", pkh: "KT1GVhG7dQNjPAt4FNBNmc9P9zpiQex4Mxob" },
+ sender: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
+ status: "confirmed",
+ timestamp: "2023-03-26T14:34:47Z",
+ type: "transaction",
+ tzktUrl: `${network.tzktExplorerUrl}/op9pGAxiJtPcv37KRnLWhYBDx2RRhTiBeTZNsKQAQ1Pxn8AsbUC`,
+ level: 2207631,
+ },
+ {
+ id: 109510819577858,
+ amount: {
+ id: 10899580518401,
+ prettyDisplay: "-1",
+ url: "https://ipfs.io/ipfs/zb2rhfbacgmTnG13DiCvjs6J21hzMeAueYVWg37C5owThnpfQ",
+ },
+ prettyTimestamp: "yesterday at 4:34 PM",
+ recipient: { type: "implicit", pkh: "tz1ikfEcj3LmsmxpcC1RMZNzBHbEmybCc43D" },
+ sender: { type: "implicit", pkh: "tz1g7Vk9dxDALJUp4w1UTnC41ssvRa7Q4XyS" },
+ timestamp: "2023-03-26T14:34:47Z",
+ type: "transaction",
+ tzktUrl: `${network.tzktExplorerUrl}/transactions/109510819577856`,
+ level: 2207631,
+ },
+ ];
+ expect(result).toEqual(expected);
+ });
- it("ignores an inactive delegation", () => {
- const result = getOperationDisplays(
- [],
- [],
- {
- id: 12345,
- sender: { address: mockImplicitAddress(1).pkh },
- timestamp: new Date().toISOString(),
- amount: 100000,
- hash: "mockHash",
- level: 300,
- bakerFee: 400,
- } as DelegationOperation,
- mockImplicitAddress(1).pkh
- );
- expect(result).toEqual([]);
+ it("includes an active delegation", () => {
+ const result = getOperationDisplays(
+ [],
+ [],
+ {
+ id: 12345,
+ sender: { address: mockImplicitAddress(1).pkh },
+ newDelegate: { address: mockImplicitAddress(1).pkh },
+ timestamp: new Date().toISOString(),
+ amount: 100000,
+ hash: "mockHash",
+ level: 300,
+ bakerFee: 400,
+ } as DelegationOperation,
+ mockImplicitAddress(1).pkh,
+ network
+ );
+ expect(result).toEqual([
+ {
+ id: 12345,
+ amount: { prettyDisplay: "0.100000 ꜩ" },
+ fee: "0.000400 ꜩ",
+ level: 300,
+ prettyTimestamp: "today at 4:15 PM",
+ recipient: { type: "implicit", pkh: "tz1UZFB9kGauB6F5c2gfJo4hVcvrD8MeJ3Vf" },
+ sender: { type: "implicit", pkh: "tz1UZFB9kGauB6F5c2gfJo4hVcvrD8MeJ3Vf" },
+ timestamp: "2023-03-27T14:15:09.760Z",
+ type: "delegation",
+ tzktUrl: `${network.tzktExplorerUrl}/mockHash`,
+ },
+ ]);
+ });
+
+ it("ignores an inactive delegation", () => {
+ const result = getOperationDisplays(
+ [],
+ [],
+ {
+ id: 12345,
+ sender: { address: mockImplicitAddress(1).pkh },
+ timestamp: new Date().toISOString(),
+ amount: 100000,
+ hash: "mockHash",
+ level: 300,
+ bakerFee: 400,
+ } as DelegationOperation,
+ mockImplicitAddress(1).pkh,
+ network
+ );
+ expect(result).toEqual([]);
+ });
});
-});
-describe("getTransactionUrl", () => {
- it("should return a proper URL", () => {
- SupportedNetworks.forEach(network => {
+ describe("getTransactionUrl", () => {
+ it("should return a proper URL", () => {
expect(
getTransactionUrl({
transactionId: 123,
@@ -616,7 +623,7 @@ describe("getTransactionUrl", () => {
migrationId: 789,
network: network,
})
- ).toEqual(`https://${network}.tzkt.io/transactions/123`);
+ ).toEqual(`${network.tzktExplorerUrl}/transactions/123`);
expect(
getTransactionUrl({
transactionId: undefined,
@@ -624,7 +631,7 @@ describe("getTransactionUrl", () => {
migrationId: 789,
network: network,
})
- ).toEqual(`https://${network}.tzkt.io/originations/456`);
+ ).toEqual(`${network.tzktExplorerUrl}/originations/456`);
expect(
getTransactionUrl({
transactionId: undefined,
@@ -632,7 +639,7 @@ describe("getTransactionUrl", () => {
migrationId: 789,
network: network,
})
- ).toEqual(`https://${network}.tzkt.io/migrations/789`);
+ ).toEqual(`${network.tzktExplorerUrl}/migrations/789`);
expect(() =>
getTransactionUrl({
transactionId: undefined,
diff --git a/src/views/operations/operationsUtils.ts b/src/views/operations/operationsUtils.ts
index 3d45fa119..798847c1f 100644
--- a/src/views/operations/operationsUtils.ts
+++ b/src/views/operations/operationsUtils.ts
@@ -9,10 +9,10 @@ import { BigNumber } from "bignumber.js";
import { prettyTezAmount } from "../../utils/format";
import { DelegationOperation } from "@tzkt/sdk-api";
import { parsePkh } from "../../types/Address";
-import { TezosNetwork } from "../../types/TezosNetwork";
+import { Network } from "../../types/Network";
-export const getHashUrl = (hash: string, network: TezosNetwork) => {
- return `https://${network}.tzkt.io/${hash}`;
+export const getHashUrl = (hash: string, network: Network) => {
+ return `${network.tzktExplorerUrl}/${hash}`;
};
export const getTransactionUrl = ({
@@ -24,16 +24,16 @@ export const getTransactionUrl = ({
transactionId: number | undefined;
originationId: number | undefined;
migrationId: number | undefined;
- network: TezosNetwork;
+ network: Network;
}) => {
if (transactionId) {
- return `https://${network}.tzkt.io/transactions/${transactionId}`;
+ return `${network.tzktExplorerUrl}/transactions/${transactionId}`;
}
if (originationId) {
- return `https://${network}.tzkt.io/originations/${originationId}`;
+ return `${network.tzktExplorerUrl}/originations/${originationId}`;
}
if (migrationId) {
- return `https://${network}.tzkt.io/migrations/${migrationId}`;
+ return `${network.tzktExplorerUrl}/migrations/${migrationId}`;
}
throw new Error("Cannot find transaction TzKT URL");
};
@@ -86,7 +86,7 @@ const TezTransaction = z.object({
export const getTezOperationDisplay = (
transfer: TezTransfer,
forAddress: string,
- network = TezosNetwork.MAINNET
+ network: Network
) => {
const parseResult = TezTransaction.safeParse(transfer);
if (!parseResult.success) {
@@ -141,7 +141,7 @@ const TokenTransaction = z.object({
export const getTokenOperationDisplay = (
transfer: TokenTransfer,
forAddress: string,
- network = TezosNetwork.MAINNET
+ network: Network
) => {
const token = fromRaw(transfer.token);
@@ -210,7 +210,7 @@ const DelegationSchema = z.object({
const getDelegationOperationDisplay = (
delegation: DelegationOperation,
- network = TezosNetwork.MAINNET
+ network: Network
): OperationDisplay | null => {
const parseResult = DelegationSchema.safeParse(delegation);
@@ -258,13 +258,13 @@ export const getOperationDisplays = (
tokenTransfers: TokenTransfer[] = [],
delegation: DelegationOperation | null = null,
forAdress: string,
- network: TezosNetwork = TezosNetwork.MAINNET
+ network: Network
) => {
return sortOperationsByTimestamp(
compact([
...tezTransfers.map(t => getTezOperationDisplay(t, forAdress, network)),
...tokenTransfers.map(t => getTokenOperationDisplay(t, forAdress, network)),
- delegation ? getDelegationOperationDisplay(delegation) : null,
+ delegation ? getDelegationOperationDisplay(delegation, network) : null,
])
);
};
diff --git a/src/views/tokens/AccountTokensTile.tsx b/src/views/tokens/AccountTokensTile.tsx
index a4040f314..16f6fe4c5 100644
--- a/src/views/tokens/AccountTokensTile.tsx
+++ b/src/views/tokens/AccountTokensTile.tsx
@@ -24,10 +24,10 @@ import { Account } from "../../types/Account";
import { FA12TokenBalance, FA2TokenBalance } from "../../types/TokenBalance";
import { httpIconUri, tokenNameSafe, tokenPrettyAmount } from "../../types/Token";
import { formatPkh } from "../../utils/format";
-import { useSelectedNetwork } from "../../utils/hooks/assetsHooks";
import { buildTzktAddressUrl } from "../../utils/tzkt/helpers";
import { DynamicModalContext } from "../../components/DynamicModal";
import SendTokenFormPage from "../../components/SendFlow/Token/FormPage";
+import { useSelectedNetwork } from "../../utils/hooks/networkHooks";
const AccountTokensTileHeader: React.FC<{
pkh: string;
diff --git a/src/views/tokens/TokensView.test.tsx b/src/views/tokens/TokensView.test.tsx
index 1847944bc..81dd0ccfa 100644
--- a/src/views/tokens/TokensView.test.tsx
+++ b/src/views/tokens/TokensView.test.tsx
@@ -3,12 +3,13 @@ import { hedgehoge, tzBtsc } from "../../mocks/fa12Tokens";
import { uUSD } from "../../mocks/fa2Tokens";
import { mockImplicitAccount, mockImplicitAddress } from "../../mocks/factories";
import { ReduxStore } from "../../providers/ReduxStore";
-import { SupportedNetworks } from "../../utils/network";
import store from "../../utils/redux/store";
import { tokensActions } from "../../utils/redux/slices/tokensSlice";
import TokensView from "./TokensView";
import accountsSlice from "../../utils/redux/slices/accountsSlice";
-import assetsSlice, { assetsActions } from "../../utils/redux/slices/assetsSlice";
+import assetsSlice from "../../utils/redux/slices/assetsSlice";
+import { DefaultNetworks } from "../../types/Network";
+import { networksActions } from "../../utils/redux/slices/networks";
const fixture = () => (
@@ -26,8 +27,8 @@ describe("", () => {
expect(screen.getByText(/no tokens found/i)).toBeInTheDocument();
});
- test.each(SupportedNetworks)("shows all available tokens from all accounts on %s", network => {
- store.dispatch(assetsActions.updateNetwork(network));
+ test.each(DefaultNetworks)("shows all available tokens from all accounts on $name", network => {
+ store.dispatch(networksActions.setCurrent(network));
store.dispatch(accountsSlice.actions.addAccount([mockImplicitAccount(1)]));
const tokenBalances = [
hedgehoge(mockImplicitAddress(0)),
diff --git a/yarn.lock b/yarn.lock
index 8e32dd58a..cd20ce4b3 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -13500,6 +13500,28 @@ __metadata:
languageName: node
linkType: hard
+"eslint-plugin-unused-imports@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "eslint-plugin-unused-imports@npm:3.0.0"
+ dependencies:
+ eslint-rule-composer: ^0.3.0
+ peerDependencies:
+ "@typescript-eslint/eslint-plugin": ^6.0.0
+ eslint: ^8.0.0
+ peerDependenciesMeta:
+ "@typescript-eslint/eslint-plugin":
+ optional: true
+ checksum: 51666f62cc8dccba2895ced83f3c1e0b78b68c357e17360e156c4db548bfdeda34cbd8725192fb4903f22d5069400fb22ded6039631df01ee82fd618dc307247
+ languageName: node
+ linkType: hard
+
+"eslint-rule-composer@npm:^0.3.0":
+ version: 0.3.0
+ resolution: "eslint-rule-composer@npm:0.3.0"
+ checksum: c2f57cded8d1c8f82483e0ce28861214347e24fd79fd4144667974cd334d718f4ba05080aaef2399e3bbe36f7d6632865110227e6b176ed6daa2d676df9281b1
+ languageName: node
+ linkType: hard
+
"eslint-scope@npm:5.1.1, eslint-scope@npm:^5.1.1":
version: 5.1.1
resolution: "eslint-scope@npm:5.1.1"
@@ -23720,6 +23742,7 @@ __metadata:
electronmon: ^2.0.2
eslint: ^8.47.0
eslint-plugin-storybook: ^0.6.13
+ eslint-plugin-unused-imports: ^3.0.0
framer-motion: ^10.15.2
graphql: ^16.8.0
graphql-request: ^6.1.0