kopia lustrzana https://github.com/bugout-dev/moonstream
Merge branch 'main' into address-identity
commit
ce1d114e14
|
@ -4,6 +4,11 @@ on:
|
|||
push:
|
||||
paths:
|
||||
- "frontend/**"
|
||||
pull_request:
|
||||
branches:
|
||||
- "main"
|
||||
paths:
|
||||
- "frontend/**"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# moonstream crawlers
|
||||
# Moonstream Crawlers
|
||||
|
||||
## Installation
|
||||
|
||||
|
@ -24,13 +24,13 @@ This crawler retrieves Ethereum function signatures from the Ethereum Signature
|
|||
#### Crawling ESD function signatures
|
||||
|
||||
```bash
|
||||
python -m moonstreamcrawlers.esd --interval 0.3 functions
|
||||
python -m mooncrawl.esd --interval 0.3 functions
|
||||
```
|
||||
|
||||
#### Crawling ESD event signatures
|
||||
|
||||
```bash
|
||||
python -m moonstreamcrawlers.esd --interval 0.3 events
|
||||
python -m mooncrawl.esd --interval 0.3 events
|
||||
```
|
||||
|
||||
### Ethereum contract registrar
|
||||
|
@ -41,17 +41,17 @@ addresses from transaction receipts.
|
|||
To run this crawler:
|
||||
|
||||
```bash
|
||||
python -m moonstreamcrawlers.cli ethcrawler contracts update
|
||||
python -m mooncrawl.cli ethcrawler contracts update
|
||||
```
|
||||
|
||||
Output is JSON list of pairs `[..., (<transaction_hash>, <contract_address>), ...]`, so you can pipe to `jq`:
|
||||
|
||||
```bash
|
||||
python -m moonstreamcrawlers.cli ethcrawler contracts update | jq .
|
||||
python -m mooncrawl.cli ethcrawler contracts update | jq .
|
||||
```
|
||||
|
||||
You can also specify an output file:
|
||||
|
||||
```bash
|
||||
python -m moonstreamcrawlers.cli ethcrawler contracts update -o new_contracts.json
|
||||
python -m mooncrawl.cli ethcrawler contracts update -o new_contracts.json
|
||||
```
|
||||
|
|
|
@ -82,9 +82,7 @@ def ethcrawler_blocks_sync_handler(args: argparse.Namespace) -> None:
|
|||
"""
|
||||
starting_block: int = args.start
|
||||
while True:
|
||||
bottom_block_number, top_block_number = get_latest_blocks(
|
||||
with_transactions=not args.notransactions
|
||||
)
|
||||
bottom_block_number, top_block_number = get_latest_blocks(args.confirmations)
|
||||
bottom_block_number = max(bottom_block_number + 1, starting_block)
|
||||
if bottom_block_number >= top_block_number:
|
||||
print(
|
||||
|
@ -210,6 +208,13 @@ def main() -> None:
|
|||
default=0,
|
||||
help="(Optional) Block to start synchronization from. Default: 0",
|
||||
)
|
||||
parser_ethcrawler_blocks_sync.add_argument(
|
||||
"-c",
|
||||
"--confirmations",
|
||||
type=int,
|
||||
default=0,
|
||||
help="Number of confirmations we require before storing a block in the database. (Default: 0)",
|
||||
)
|
||||
parser_ethcrawler_blocks_sync.add_argument(
|
||||
"--order",
|
||||
type=processing_order,
|
|
@ -14,6 +14,12 @@ from moonstreamdb.models import (
|
|||
)
|
||||
|
||||
|
||||
class EthereumBlockCrawlError(Exception):
|
||||
"""
|
||||
Raised when there is a problem crawling Ethereum blocks.
|
||||
"""
|
||||
|
||||
|
||||
def connect(web3_uri: Optional[str] = MOONSTREAM_IPC_PATH):
|
||||
web3_provider: Union[IPCProvider, HTTPProvider] = Web3.IPCProvider()
|
||||
if web3_uri is not None:
|
||||
|
@ -71,24 +77,29 @@ def add_block_transactions(db_session, block: BlockData) -> None:
|
|||
db_session.add(tx_obj)
|
||||
|
||||
|
||||
def get_latest_blocks(with_transactions: bool = False) -> Tuple[Optional[int], int]:
|
||||
def get_latest_blocks(confirmations: int = 0) -> Tuple[Optional[int], int]:
|
||||
"""
|
||||
Retrieve the latest block from the connected node (connection is created by the connect() method).
|
||||
|
||||
If confirmations > 0, and the latest block on the node has block number N, this returns the block
|
||||
with block_number (N - confirmations)
|
||||
"""
|
||||
web3_client = connect()
|
||||
block_latest: BlockData = web3_client.eth.get_block(
|
||||
"latest", full_transactions=with_transactions
|
||||
)
|
||||
latest_block_number: int = web3_client.eth.block_number
|
||||
if confirmations > 0:
|
||||
latest_block_number -= confirmations
|
||||
|
||||
with yield_db_session_ctx() as db_session:
|
||||
block_number_latest_exist_row = (
|
||||
latest_stored_block_row = (
|
||||
db_session.query(EthereumBlock.block_number)
|
||||
.order_by(EthereumBlock.block_number.desc())
|
||||
.first()
|
||||
)
|
||||
block_number_latest_exist = (
|
||||
None
|
||||
if block_number_latest_exist_row is None
|
||||
else block_number_latest_exist_row[0]
|
||||
latest_stored_block_number = (
|
||||
None if latest_stored_block_row is None else latest_stored_block_row[0]
|
||||
)
|
||||
|
||||
return block_number_latest_exist, block_latest.number
|
||||
return latest_stored_block_number, latest_block_number
|
||||
|
||||
|
||||
def crawl_blocks(
|
||||
|
@ -98,20 +109,31 @@ def crawl_blocks(
|
|||
Open database and geth sessions and fetch block data from blockchain.
|
||||
"""
|
||||
web3_client = connect()
|
||||
for block_number in blocks_numbers:
|
||||
with yield_db_session_ctx() as db_session:
|
||||
block: BlockData = web3_client.eth.get_block(
|
||||
block_number, full_transactions=with_transactions
|
||||
)
|
||||
add_block(db_session, block)
|
||||
with yield_db_session_ctx() as db_session:
|
||||
for block_number in blocks_numbers:
|
||||
try:
|
||||
block: BlockData = web3_client.eth.get_block(
|
||||
block_number, full_transactions=with_transactions
|
||||
)
|
||||
add_block(db_session, block)
|
||||
|
||||
if with_transactions:
|
||||
add_block_transactions(db_session, block)
|
||||
if with_transactions:
|
||||
add_block_transactions(db_session, block)
|
||||
|
||||
db_session.commit()
|
||||
db_session.commit()
|
||||
except Exception as err:
|
||||
db_session.rollback()
|
||||
message = f"Error adding block (number={block_number}) to database:\n{repr(err)}"
|
||||
raise EthereumBlockCrawlError(message)
|
||||
except:
|
||||
db_session.rollback()
|
||||
print(
|
||||
f"Interrupted while adding block (number={block_number}) to database."
|
||||
)
|
||||
raise
|
||||
|
||||
if verbose:
|
||||
print(f"Added {block_number} block")
|
||||
print(f"Added block: {block_number}")
|
||||
|
||||
|
||||
def check_missing_blocks(blocks_numbers: List[int]) -> List[int]:
|
||||
|
@ -143,6 +165,15 @@ def crawl_blocks_executor(
|
|||
) -> None:
|
||||
"""
|
||||
Execute crawler in processes.
|
||||
|
||||
Args:
|
||||
block_numbers_list - List of block numbers to add to database.
|
||||
with_transactions - If True, also adds transactions from those blocks to the ethereum_transactions table.
|
||||
verbose - Print logs to stdout?
|
||||
num_processes - Number of processes to use to feed blocks into database.
|
||||
|
||||
Returns nothing, but if there was an error processing the given blocks it raises an EthereumBlocksCrawlError.
|
||||
The error message is a list of all the things that went wrong in the crawl.
|
||||
"""
|
||||
errors: List[Exception] = []
|
||||
|
||||
|
@ -173,12 +204,10 @@ def crawl_blocks_executor(
|
|||
results.append(result)
|
||||
|
||||
wait(results)
|
||||
# TODO(kompotkot): Return list of errors and colors responsible for
|
||||
# handling errors
|
||||
if len(errors) > 0:
|
||||
print("Errors:")
|
||||
for error in errors:
|
||||
print(f"- {error}")
|
||||
error_messages = "\n".join([f"- {error}" for error in errors])
|
||||
message = f"Error processing blocks in list:\n{error_messages}"
|
||||
raise EthereumBlockCrawlError(message)
|
||||
|
||||
|
||||
def process_contract_deployments() -> List[Tuple[str, str]]:
|
|
@ -2,4 +2,4 @@
|
|||
Moonstream crawlers version.
|
||||
"""
|
||||
|
||||
MOONSTREAMCRAWLERS_VERSION = "0.0.1"
|
||||
MOONCRAWL_VERSION = "0.0.2"
|
|
@ -1,14 +1,14 @@
|
|||
from setuptools import find_packages, setup
|
||||
|
||||
from moonstreamcrawlers.version import MOONSTREAMCRAWLERS_VERSION
|
||||
from mooncrawl.version import MOONCRAWL_VERSION
|
||||
|
||||
long_description = ""
|
||||
with open("README.md") as ifp:
|
||||
long_description = ifp.read()
|
||||
|
||||
setup(
|
||||
name="moonstreamcrawlers",
|
||||
version=MOONSTREAMCRAWLERS_VERSION,
|
||||
name="mooncrawl",
|
||||
version=MOONCRAWL_VERSION,
|
||||
author="Bugout.dev",
|
||||
author_email="engineers@bugout.dev",
|
||||
license="Apache License 2.0",
|
||||
|
@ -30,7 +30,7 @@ setup(
|
|||
],
|
||||
python_requires=">=3.6",
|
||||
packages=find_packages(),
|
||||
package_data={"moonstreamcrawlers": ["py.typed"]},
|
||||
package_data={"mooncrawl": ["py.typed"]},
|
||||
zip_safe=False,
|
||||
install_requires=[
|
||||
"moonstreamdb @ git+https://git@github.com/bugout-dev/moonstream.git@ec3278e192119d1e8a273cfaab6cb53890d2e8e9#egg=moonstreamdb&subdirectory=db",
|
||||
|
@ -41,9 +41,9 @@ setup(
|
|||
extras_require={"dev": ["black", "mypy", "types-requests"]},
|
||||
entry_points={
|
||||
"console_scripts": [
|
||||
"ethcrawler=moonstreamcrawlers.ethcrawler:main",
|
||||
"esd=moonstreamcrawlers.esd:main",
|
||||
"identity=moonstreamcrawlers.identity:main"
|
||||
"ethcrawler=mooncrawl.ethcrawler:main",
|
||||
"esd=mooncrawl.esd:main",
|
||||
"identity=mooncrawl.identity:main"
|
||||
]
|
||||
},
|
||||
)
|
||||
|
|
|
@ -16,12 +16,15 @@
|
|||
"@emotion/styled": "^11.3.0",
|
||||
"@stripe/stripe-js": "^1.16.0",
|
||||
"axios": "^0.21.1",
|
||||
"focus-visible": "^5.2.0",
|
||||
"framer-motion": "^4.1.17",
|
||||
"mixpanel-browser": "^2.41.0",
|
||||
"moment": "^2.29.1",
|
||||
"next": "11.0.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"react": "^17.0.2",
|
||||
"react-calendly": "^2.2.1",
|
||||
"react-color": "^2.19.3",
|
||||
"react-copy-to-clipboard": "^5.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-hook-form": "^6.9.2",
|
||||
|
|
|
@ -1,49 +1,74 @@
|
|||
import React from "react";
|
||||
import { React, useEffect, useState } from "react";
|
||||
import "/styles/styles.css";
|
||||
import "/styles/nprogress.css";
|
||||
import "/styles/sidebar.css";
|
||||
import "highlight.js/styles/github.css";
|
||||
import App from "next/app";
|
||||
import "focus-visible/dist/focus-visible";
|
||||
import dynamic from "next/dynamic";
|
||||
import { QueryClient, QueryClientProvider } from "react-query";
|
||||
import HeadSEO from "../src/components/HeadSEO";
|
||||
import HeadLinks from "../src/components/HeadLinks";
|
||||
|
||||
const HeadSEO = dynamic(() => import("../src/components/HeadSEO"), {
|
||||
ssr: false,
|
||||
});
|
||||
const HeadLinks = dynamic(() => import("../src/components/HeadLinks"), {
|
||||
ssr: false,
|
||||
});
|
||||
const AppContext = dynamic(() => import("../src/AppContext"), {
|
||||
ssr: false,
|
||||
});
|
||||
const DefaultLayout = dynamic(() => import("../src/layouts"), {
|
||||
ssr: false,
|
||||
});
|
||||
import { useRouter } from "next/router";
|
||||
import NProgress from "nprogress";
|
||||
|
||||
export default class CachingApp extends App {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { queryClient: new QueryClient() };
|
||||
}
|
||||
export default function CachingApp({ Component, pageProps }) {
|
||||
const [queryClient] = useState(new QueryClient());
|
||||
|
||||
render() {
|
||||
const { Component, pageProps } = this.props;
|
||||
const getLayout =
|
||||
Component.getLayout || ((page) => <DefaultLayout>{page}</DefaultLayout>);
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<>
|
||||
<style global jsx>{`
|
||||
html,
|
||||
body,
|
||||
body > div:first-child,
|
||||
div#__next,
|
||||
div#__next > div {
|
||||
height: 100% !important;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
`}</style>
|
||||
{pageProps.metaTags && <HeadSEO {...pageProps.metaTags} />}
|
||||
{pageProps.preloads && <HeadLinks links={pageProps.preloads} />}
|
||||
<QueryClientProvider client={this.state.queryClient}>
|
||||
<AppContext>{getLayout(<Component {...pageProps} />)}</AppContext>
|
||||
</QueryClientProvider>
|
||||
</>
|
||||
);
|
||||
}
|
||||
useEffect(() => {
|
||||
const handleStart = () => {
|
||||
NProgress.start();
|
||||
};
|
||||
const handleStop = () => {
|
||||
NProgress.done();
|
||||
};
|
||||
|
||||
router.events.on("routeChangeStart", handleStart);
|
||||
router.events.on("routeChangeComplete", handleStop);
|
||||
router.events.on("routeChangeError", handleStop);
|
||||
|
||||
console.log("_app", router.asPath);
|
||||
return () => {
|
||||
router.events.off("routeChangeStart", handleStart);
|
||||
router.events.off("routeChangeComplete", handleStop);
|
||||
router.events.off("routeChangeError", handleStop);
|
||||
};
|
||||
}, [router]);
|
||||
const getLayout =
|
||||
Component.getLayout || ((page) => <DefaultLayout>{page}</DefaultLayout>);
|
||||
|
||||
console.log("_app loaded", router.asPath);
|
||||
|
||||
return (
|
||||
<>
|
||||
<style global jsx>{`
|
||||
html,
|
||||
body,
|
||||
body > div:first-child,
|
||||
div#__next,
|
||||
div#__next > div {
|
||||
height: 100% !important;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
`}</style>
|
||||
{pageProps.metaTags && <HeadSEO {...pageProps.metaTags} />}
|
||||
{pageProps.preloads && <HeadLinks links={pageProps.preloads} />}
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<AppContext>{getLayout(<Component {...pageProps} />)}</AppContext>
|
||||
</QueryClientProvider>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,42 +1,80 @@
|
|||
import React, {
|
||||
useLayoutEffect,
|
||||
useEffect,
|
||||
Suspense,
|
||||
useContext,
|
||||
useState,
|
||||
useContext,
|
||||
Suspense,
|
||||
useEffect,
|
||||
useLayoutEffect,
|
||||
} from "react";
|
||||
import {
|
||||
Fade,
|
||||
Flex,
|
||||
Heading,
|
||||
Box,
|
||||
Image as ChakraImage,
|
||||
Button,
|
||||
Center,
|
||||
Fade,
|
||||
chakra,
|
||||
Stack,
|
||||
Link,
|
||||
SimpleGrid,
|
||||
useMediaQuery,
|
||||
Grid,
|
||||
GridItem,
|
||||
} from "@chakra-ui/react";
|
||||
import { Grid, GridItem } from "@chakra-ui/react";
|
||||
import { useUser, useAnalytics, useModals, useRouter } from "../src/core/hooks";
|
||||
import { getLayout } from "../src/layouts";
|
||||
import SplitWithImage from "../src/components/SplitWithImage";
|
||||
import ConnectedButtons from "../src/components/ConnectedButtons";
|
||||
import UIContext from "../src/core/providers/UIProvider/context";
|
||||
import dynamic from "next/dynamic";
|
||||
import useUser from "../src/core/hooks/useUser";
|
||||
import useAnalytics from "../src/core/hooks/useAnalytics";
|
||||
import useModals from "../src/core/hooks/useModals";
|
||||
import useRouter from "../src/core/hooks/useRouter";
|
||||
import { MIXPANEL_PROPS } from "../src/core/providers/AnalyticsProvider/constants";
|
||||
import { FaFileContract } from "react-icons/fa";
|
||||
import { RiDashboardFill } from "react-icons/ri";
|
||||
import {
|
||||
GiMeshBall,
|
||||
GiLogicGateXor,
|
||||
GiSuspicious,
|
||||
GiHook,
|
||||
} from "react-icons/gi";
|
||||
import { AiFillApi } from "react-icons/ai";
|
||||
import { BiTransfer } from "react-icons/bi";
|
||||
import { IoTelescopeSharp } from "react-icons/io5";
|
||||
import UIContext from "../src/core/providers/UIProvider/context";
|
||||
|
||||
const SplitWithImage = dynamic(
|
||||
() => import("../src/components/SplitWithImage"),
|
||||
{
|
||||
ssr: false,
|
||||
}
|
||||
);
|
||||
const ConnectedButtons = dynamic(
|
||||
() => import("../src/components/ConnectedButtons"),
|
||||
{
|
||||
ssr: false,
|
||||
}
|
||||
);
|
||||
|
||||
const RiDashboardFill = dynamic(() =>
|
||||
import("react-icons/ri").then((mod) => mod.RiDashboardFill)
|
||||
);
|
||||
const FaFileContract = dynamic(() =>
|
||||
import("react-icons/fa").then((mod) => mod.FaFileContract)
|
||||
);
|
||||
const GiMeshBall = dynamic(() =>
|
||||
import("react-icons/gi").then((mod) => mod.GiMeshBall)
|
||||
);
|
||||
|
||||
const GiLogicGateXor = dynamic(() =>
|
||||
import("react-icons/gi").then((mod) => mod.GiLogicGateXor)
|
||||
);
|
||||
|
||||
const GiSuspicious = dynamic(() =>
|
||||
import("react-icons/gi").then((mod) => mod.GiSuspicious)
|
||||
);
|
||||
|
||||
const GiHook = dynamic(() =>
|
||||
import("react-icons/gi").then((mod) => mod.GiHook)
|
||||
);
|
||||
|
||||
const AiFillApi = dynamic(() =>
|
||||
import("react-icons/ai").then((mod) => mod.AiFillApi)
|
||||
);
|
||||
|
||||
const BiTransfer = dynamic(() =>
|
||||
import("react-icons/bi").then((mod) => mod.BiTransfer)
|
||||
);
|
||||
|
||||
const IoTelescopeSharp = dynamic(() =>
|
||||
import("react-icons/io5").then((mod) => mod.IoTelescopeSharp)
|
||||
);
|
||||
|
||||
const HEADING_PROPS = {
|
||||
fontWeight: "700",
|
||||
|
@ -114,11 +152,16 @@ const Homepage = () => {
|
|||
if (
|
||||
router.nextRouter.asPath !== "/" &&
|
||||
router.nextRouter.asPath.slice(0, 2) !== "/?" &&
|
||||
router.nextRouter.asPath.slice(0, 2) !== "/#"
|
||||
router.nextRouter.asPath.slice(0, 2) !== "/#" &&
|
||||
router.nextRouter.asPath.slice(0, 11) !== "/index.html"
|
||||
) {
|
||||
router.replace(router.nextRouter.asPath, undefined, {
|
||||
shallow: true,
|
||||
});
|
||||
console.warn("redirect attempt..");
|
||||
if (typeof window !== "undefined") {
|
||||
console.warn("window present:", window.location.pathname);
|
||||
router.replace(router.nextRouter.asPath, router.nextRouter.asPath, {
|
||||
shallow: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [isInit, router]);
|
||||
|
||||
|
@ -155,351 +198,352 @@ const Homepage = () => {
|
|||
}, []);
|
||||
|
||||
return (
|
||||
<Fade in>
|
||||
<Box
|
||||
width="100%"
|
||||
flexDirection="column"
|
||||
sx={{ scrollBehavior: "smooth" }}
|
||||
bgSize="cover"
|
||||
>
|
||||
<Flex
|
||||
direction="column"
|
||||
h="auto"
|
||||
position="relative"
|
||||
w="100%"
|
||||
overflow="initial"
|
||||
pt={0}
|
||||
<Suspense fallback="">
|
||||
<Fade in>
|
||||
<Box
|
||||
width="100%"
|
||||
flexDirection="column"
|
||||
sx={{ scrollBehavior: "smooth" }}
|
||||
bgSize="cover"
|
||||
>
|
||||
<Suspense fallback={""}></Suspense>
|
||||
|
||||
<Grid
|
||||
templateColumns="repeat(12,1fr)"
|
||||
mt={0}
|
||||
border="none"
|
||||
boxSizing="content-box"
|
||||
<Flex
|
||||
direction="column"
|
||||
h="auto"
|
||||
position="relative"
|
||||
w="100%"
|
||||
overflow="initial"
|
||||
pt={0}
|
||||
>
|
||||
<GridItem
|
||||
<Suspense fallback={""}></Suspense>
|
||||
|
||||
<Grid
|
||||
templateColumns="repeat(12,1fr)"
|
||||
mt={0}
|
||||
px="0"
|
||||
colSpan="12"
|
||||
pb={[1, 2, null, 8]}
|
||||
minH="100vh"
|
||||
// bgColor="primary.1200"
|
||||
border="none"
|
||||
boxSizing="content-box"
|
||||
>
|
||||
<chakra.header boxSize="full" minH="100vh">
|
||||
<Box
|
||||
bgPos="bottom"
|
||||
bgColor="transparent"
|
||||
backgroundImage={`url(${assets[`${background}`]})`}
|
||||
bgSize="cover"
|
||||
boxSize="full"
|
||||
minH="100vh"
|
||||
>
|
||||
<Flex align="center" justify="center" boxSize="full">
|
||||
<Stack
|
||||
textAlign="center"
|
||||
alignItems="center"
|
||||
spacing={6}
|
||||
maxW="1620px"
|
||||
px="7%"
|
||||
h="100%"
|
||||
pt={["10vh", null, "30vh"]}
|
||||
>
|
||||
<Heading size="2xl" fontWeight="semibold" color="white">
|
||||
All the crypto data you care about in a single stream
|
||||
</Heading>
|
||||
<chakra.span
|
||||
my={12}
|
||||
fontSize={["lg", null, "xl"]}
|
||||
display="inline-block"
|
||||
color="primary.200"
|
||||
textDecor="underline"
|
||||
>
|
||||
Get all the crypto data you need in a single stream.
|
||||
From pending transactions in the Ethereum transaction
|
||||
pool to Elon Musk’s latest tweets.
|
||||
</chakra.span>
|
||||
<chakra.span
|
||||
fontSize={["lg", null, "xl"]}
|
||||
display="inline-block"
|
||||
color="primary.300"
|
||||
textDecor="underline"
|
||||
>
|
||||
Access this data through the Moonstream dashboard or API
|
||||
</chakra.span>
|
||||
</Stack>
|
||||
</Flex>
|
||||
</Box>
|
||||
</chakra.header>
|
||||
</GridItem>
|
||||
|
||||
<GridItem
|
||||
px="7%"
|
||||
colSpan="12"
|
||||
pt={["20px", "20px", "100px", null, "120px"]}
|
||||
pb={["20px", "56px", null, "184px"]}
|
||||
minH="100vh"
|
||||
>
|
||||
<Heading
|
||||
{...HEADING_PROPS}
|
||||
textAlign="center"
|
||||
pb={[12, 12, 12, null, 48]}
|
||||
<GridItem
|
||||
mt={0}
|
||||
px="0"
|
||||
colSpan="12"
|
||||
pb={[1, 2, null, 8]}
|
||||
minH="100vh"
|
||||
// bgColor="primary.1200"
|
||||
>
|
||||
Data you can add to your stream:
|
||||
</Heading>
|
||||
<chakra.header boxSize="full" minH="100vh">
|
||||
<Box
|
||||
bgPos="bottom"
|
||||
bgColor="transparent"
|
||||
backgroundImage={`url(${assets[`${background}`]})`}
|
||||
bgSize="cover"
|
||||
boxSize="full"
|
||||
minH="100vh"
|
||||
>
|
||||
<Flex align="center" justify="center" boxSize="full">
|
||||
<Stack
|
||||
textAlign="center"
|
||||
alignItems="center"
|
||||
spacing={6}
|
||||
maxW="1620px"
|
||||
px="7%"
|
||||
h="100%"
|
||||
pt={["10vh", null, "20vh"]}
|
||||
>
|
||||
<Heading size="2xl" fontWeight="semibold" color="white">
|
||||
All the crypto data you care about in a single stream
|
||||
</Heading>
|
||||
<chakra.span
|
||||
my={12}
|
||||
fontSize={["lg", null, "xl"]}
|
||||
display="inline-block"
|
||||
color="primary.200"
|
||||
>
|
||||
Get all the crypto data you need in a single stream.
|
||||
From pending transactions in the Ethereum transaction
|
||||
pool to Elon Musk’s latest tweets.
|
||||
</chakra.span>
|
||||
<chakra.span
|
||||
fontSize={["lg", null, "xl"]}
|
||||
display="inline-block"
|
||||
color="primary.300"
|
||||
>
|
||||
Access this data through the Moonstream dashboard or
|
||||
API
|
||||
</chakra.span>
|
||||
</Stack>
|
||||
</Flex>
|
||||
</Box>
|
||||
</chakra.header>
|
||||
</GridItem>
|
||||
|
||||
<SimpleGrid columns={[1, 2, 2, 4, null, 4]}>
|
||||
<Stack spacing={1} px={1} alignItems="center">
|
||||
<ChakraImage
|
||||
boxSize={["220px", "220px", "xs", null, "xs"]}
|
||||
objectFit="contain"
|
||||
src={assets["minedTransactions"]}
|
||||
alt="mined transactions"
|
||||
/>
|
||||
<Heading textAlign="center ">
|
||||
Ethereum mined transactions
|
||||
</Heading>
|
||||
</Stack>
|
||||
<Stack spacing={1} px={1} alignItems="center">
|
||||
<ChakraImage
|
||||
boxSize={["220px", "220px", "xs", null, "xs"]}
|
||||
objectFit="contain"
|
||||
src={assets["pendingTransactions"]}
|
||||
alt="mined transactions"
|
||||
/>
|
||||
<Heading textAlign="center ">
|
||||
Ethereum pending transactions
|
||||
</Heading>
|
||||
</Stack>
|
||||
<Stack spacing={1} px={1} alignItems="center">
|
||||
<ChakraImage
|
||||
boxSize={["220px", "220px", "xs", null, "xs"]}
|
||||
objectFit="contain"
|
||||
src={assets["priceInformation"]}
|
||||
alt="mined transactions"
|
||||
/>
|
||||
<Heading textAlign="center ">Centralized exchanges</Heading>
|
||||
</Stack>
|
||||
<Stack spacing={1} px={1} alignItems="center">
|
||||
<ChakraImage
|
||||
boxSize={["220px", "220px", "xs", null, "xs"]}
|
||||
objectFit="contain"
|
||||
src={assets["socialMediaPosts"]}
|
||||
alt="mined transactions"
|
||||
/>
|
||||
<Heading textAlign="center ">Social media posts</Heading>
|
||||
</Stack>
|
||||
</SimpleGrid>
|
||||
<Center>
|
||||
<Heading pt="160px" pb="60px">
|
||||
Moonstream is ment for you if
|
||||
<GridItem
|
||||
px="7%"
|
||||
colSpan="12"
|
||||
pt={["20px", "20px", "100px", null, "120px"]}
|
||||
pb={["20px", "56px", null, "184px"]}
|
||||
minH="100vh"
|
||||
>
|
||||
<Heading
|
||||
{...HEADING_PROPS}
|
||||
textAlign="center"
|
||||
pb={[12, 12, 12, null, 48]}
|
||||
>
|
||||
Data you can add to your stream:
|
||||
</Heading>
|
||||
</Center>
|
||||
<Flex
|
||||
w="100%"
|
||||
direction={["column", "row", "column", null, "column"]}
|
||||
flexWrap={["nowrap", "nowrap", "nowrap", null, "nowrap"]}
|
||||
pb="66px"
|
||||
>
|
||||
<ConnectedButtons
|
||||
title={"You are..."}
|
||||
button1={{
|
||||
label: "Crypto trader",
|
||||
link: "/#cryptoTrader",
|
||||
onClick: () => {
|
||||
track(`${MIXPANEL_EVENTS.BUTTON_CLICKED}`, {
|
||||
[`${MIXPANEL_PROPS.BUTTON_CLICKED}`]: `scroll to CryptoTrader`,
|
||||
});
|
||||
},
|
||||
}}
|
||||
button2={{
|
||||
label: "Algorithmic Fund",
|
||||
link: "/#algoFund",
|
||||
onClick: () => {
|
||||
track(`${MIXPANEL_EVENTS.BUTTON_CLICKED}`, {
|
||||
[`${MIXPANEL_PROPS.BUTTON_CLICKED}`]: `scroll to AlgoFund`,
|
||||
});
|
||||
},
|
||||
}}
|
||||
button3={{
|
||||
label: "Developer",
|
||||
link: "/#smartDeveloper",
|
||||
onClick: () => {
|
||||
track(`${MIXPANEL_EVENTS.BUTTON_CLICKED}`, {
|
||||
[`${MIXPANEL_PROPS.BUTTON_CLICKED}`]: `scroll to Developer`,
|
||||
});
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
</GridItem>
|
||||
<GridItem
|
||||
px="7%"
|
||||
colSpan="12"
|
||||
pt={["1rem", "1rem", "5.125rem", null, "5.125rem"]}
|
||||
pb={["0", "66px", null, "66px"]}
|
||||
id="cryptoTrader"
|
||||
minH={ui.isMobileView ? "100vh" : null}
|
||||
>
|
||||
<SplitWithImage
|
||||
cta={{
|
||||
label: "I want early access!",
|
||||
onClick: () => {
|
||||
track(`${MIXPANEL_EVENTS.BUTTON_CLICKED}`, {
|
||||
[`${MIXPANEL_PROPS.BUTTON_CLICKED}`]: `Early access CTA: Crypto trader`,
|
||||
});
|
||||
toggleModal("hubspot-trader");
|
||||
},
|
||||
}}
|
||||
elementName={"element1"}
|
||||
colorScheme="suggested"
|
||||
badge={`For crypto traders`}
|
||||
title={``}
|
||||
body={``}
|
||||
bullets={[
|
||||
{
|
||||
text: `Subscribe to the defi contracts you care about`,
|
||||
icon: FaFileContract,
|
||||
color: "suggested.50",
|
||||
bgColor: "suggested.900",
|
||||
},
|
||||
{
|
||||
text: `Make sense of how others are calling these contracts using Moonstream dashboards.
|
||||
`,
|
||||
icon: RiDashboardFill,
|
||||
color: "suggested.50",
|
||||
bgColor: "suggested.900",
|
||||
},
|
||||
{
|
||||
text: `Get data directly from the transaction pool through our global network of Ethereum nodes`,
|
||||
icon: GiMeshBall,
|
||||
color: "suggested.50",
|
||||
bgColor: "suggested.900",
|
||||
},
|
||||
]}
|
||||
imgURL={assets["cryptoTraders"]}
|
||||
/>
|
||||
</GridItem>
|
||||
<GridItem
|
||||
px="7%"
|
||||
colSpan="12"
|
||||
pt={["1rem", "1rem", "5.125rem", null, "5.125rem"]}
|
||||
pb={["0", "66px", null, "66px"]}
|
||||
id="algoFund"
|
||||
minH={ui.isMobileView ? "100vh" : null}
|
||||
>
|
||||
<SplitWithImage
|
||||
cta={{
|
||||
label: "I want early access!",
|
||||
onClick: () => {
|
||||
track(`${MIXPANEL_EVENTS.BUTTON_CLICKED}`, {
|
||||
[`${MIXPANEL_PROPS.BUTTON_CLICKED}`]: `Early access CTA: Algo fund`,
|
||||
});
|
||||
toggleModal("hubspot-fund");
|
||||
},
|
||||
}}
|
||||
elementName={"element2"}
|
||||
mirror={true}
|
||||
colorScheme="secondary"
|
||||
badge={`For algorithmic funds`}
|
||||
bullets={[
|
||||
{
|
||||
text: `Get API access to your stream`,
|
||||
icon: AiFillApi,
|
||||
color: "secondary.50",
|
||||
bgColor: "secondary.900",
|
||||
},
|
||||
{
|
||||
text: `Set conditions that trigger predefined actions`,
|
||||
icon: GiLogicGateXor,
|
||||
color: "secondary.50",
|
||||
bgColor: "secondary.900",
|
||||
},
|
||||
{
|
||||
text: `Execute transactions directly on Moonstream nodes`,
|
||||
icon: BiTransfer,
|
||||
color: "secondary.50",
|
||||
bgColor: "secondary.900",
|
||||
},
|
||||
]}
|
||||
imgURL={assets["algorithmicFunds"]}
|
||||
/>
|
||||
</GridItem>
|
||||
<GridItem
|
||||
px="7%"
|
||||
colSpan="12"
|
||||
pt={["1rem", "1rem", "5.125rem", null, "5.125rem"]}
|
||||
pb={["0", "66px", null, "66px"]}
|
||||
id="smartDeveloper"
|
||||
minH={ui.isMobileView ? "100vh" : null}
|
||||
>
|
||||
<SplitWithImage
|
||||
cta={{
|
||||
label: "I want early access!",
|
||||
onClick: () => {
|
||||
track(`${MIXPANEL_EVENTS.BUTTON_CLICKED}`, {
|
||||
[`${MIXPANEL_PROPS.BUTTON_CLICKED}`]: `Early access CTA: developer`,
|
||||
});
|
||||
toggleModal("hubspot-developer");
|
||||
},
|
||||
}}
|
||||
elementName={"element3"}
|
||||
colorScheme="primary"
|
||||
badge={`For smart contract developers`}
|
||||
bullets={[
|
||||
{
|
||||
text: `See how people use your smart contracts`,
|
||||
icon: IoTelescopeSharp,
|
||||
color: "primary.50",
|
||||
bgColor: "primary.900",
|
||||
},
|
||||
{
|
||||
text: `Set up alerts on suspicious activity`,
|
||||
icon: GiSuspicious,
|
||||
color: "primary.50",
|
||||
bgColor: "primary.900",
|
||||
},
|
||||
{
|
||||
text: `Register webhooks to connect your off-chain infrastructure`,
|
||||
icon: GiHook,
|
||||
color: "primary.50",
|
||||
bgColor: "primary.900",
|
||||
},
|
||||
]}
|
||||
imgURL={assets["smartDevelopers"]}
|
||||
/>
|
||||
</GridItem>
|
||||
<GridItem
|
||||
placeItems="center"
|
||||
w="100%"
|
||||
colSpan="12"
|
||||
pt={["0", "0", "5.125rem", null, "5.125rem"]}
|
||||
pb="120px"
|
||||
>
|
||||
<Center>
|
||||
<Button
|
||||
as={Link}
|
||||
isExternal
|
||||
href={"https://discord.gg/K56VNUQGvA"}
|
||||
size="lg"
|
||||
variant="solid"
|
||||
colorScheme="suggested"
|
||||
id="test"
|
||||
onClick={() => {
|
||||
track(`${MIXPANEL_EVENTS.BUTTON_CLICKED}`, {
|
||||
[`${MIXPANEL_PROPS.BUTTON_CLICKED}`]: `Join our discord`,
|
||||
});
|
||||
toggleModal("hubspot");
|
||||
}}
|
||||
|
||||
<SimpleGrid columns={[1, 2, 2, 4, null, 4]}>
|
||||
<Stack spacing={1} px={1} alignItems="center">
|
||||
<ChakraImage
|
||||
boxSize={["220px", "220px", "xs", null, "xs"]}
|
||||
objectFit="contain"
|
||||
src={assets["minedTransactions"]}
|
||||
alt="mined transactions"
|
||||
/>
|
||||
<Heading textAlign="center ">
|
||||
Ethereum mined transactions
|
||||
</Heading>
|
||||
</Stack>
|
||||
<Stack spacing={1} px={1} alignItems="center">
|
||||
<ChakraImage
|
||||
boxSize={["220px", "220px", "xs", null, "xs"]}
|
||||
objectFit="contain"
|
||||
src={assets["pendingTransactions"]}
|
||||
alt="mined transactions"
|
||||
/>
|
||||
<Heading textAlign="center ">
|
||||
Ethereum pending transactions
|
||||
</Heading>
|
||||
</Stack>
|
||||
<Stack spacing={1} px={1} alignItems="center">
|
||||
<ChakraImage
|
||||
boxSize={["220px", "220px", "xs", null, "xs"]}
|
||||
objectFit="contain"
|
||||
src={assets["priceInformation"]}
|
||||
alt="mined transactions"
|
||||
/>
|
||||
<Heading textAlign="center ">Centralized exchanges</Heading>
|
||||
</Stack>
|
||||
<Stack spacing={1} px={1} alignItems="center">
|
||||
<ChakraImage
|
||||
boxSize={["220px", "220px", "xs", null, "xs"]}
|
||||
objectFit="contain"
|
||||
src={assets["socialMediaPosts"]}
|
||||
alt="mined transactions"
|
||||
/>
|
||||
<Heading textAlign="center ">Social media posts</Heading>
|
||||
</Stack>
|
||||
</SimpleGrid>
|
||||
<Center>
|
||||
<Heading pt="160px" pb="60px">
|
||||
Moonstream is ment for you if
|
||||
</Heading>
|
||||
</Center>
|
||||
<Flex
|
||||
w="100%"
|
||||
direction={["column", "row", "column", null, "column"]}
|
||||
flexWrap={["nowrap", "nowrap", "nowrap", null, "nowrap"]}
|
||||
pb="66px"
|
||||
>
|
||||
Join our discord
|
||||
</Button>
|
||||
</Center>
|
||||
</GridItem>
|
||||
</Grid>
|
||||
</Flex>
|
||||
</Box>
|
||||
</Fade>
|
||||
<ConnectedButtons
|
||||
title={"You are..."}
|
||||
button1={{
|
||||
label: "Crypto trader",
|
||||
link: "/#cryptoTrader",
|
||||
onClick: () => {
|
||||
track(`${MIXPANEL_EVENTS.BUTTON_CLICKED}`, {
|
||||
[`${MIXPANEL_PROPS.BUTTON_CLICKED}`]: `scroll to CryptoTrader`,
|
||||
});
|
||||
},
|
||||
}}
|
||||
button2={{
|
||||
label: "Algorithmic Fund",
|
||||
link: "/#algoFund",
|
||||
onClick: () => {
|
||||
track(`${MIXPANEL_EVENTS.BUTTON_CLICKED}`, {
|
||||
[`${MIXPANEL_PROPS.BUTTON_CLICKED}`]: `scroll to AlgoFund`,
|
||||
});
|
||||
},
|
||||
}}
|
||||
button3={{
|
||||
label: "Developer",
|
||||
link: "/#smartDeveloper",
|
||||
onClick: () => {
|
||||
track(`${MIXPANEL_EVENTS.BUTTON_CLICKED}`, {
|
||||
[`${MIXPANEL_PROPS.BUTTON_CLICKED}`]: `scroll to Developer`,
|
||||
});
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
</GridItem>
|
||||
<GridItem
|
||||
px="7%"
|
||||
colSpan="12"
|
||||
pt={["1rem", "1rem", "5.125rem", null, "5.125rem"]}
|
||||
pb={["0", "66px", null, "66px"]}
|
||||
id="cryptoTrader"
|
||||
minH={ui.isMobileView ? "100vh" : null}
|
||||
>
|
||||
<SplitWithImage
|
||||
cta={{
|
||||
label: "I want early access!",
|
||||
onClick: () => {
|
||||
track(`${MIXPANEL_EVENTS.BUTTON_CLICKED}`, {
|
||||
[`${MIXPANEL_PROPS.BUTTON_CLICKED}`]: `Early access CTA: Crypto trader`,
|
||||
});
|
||||
toggleModal("hubspot-trader");
|
||||
},
|
||||
}}
|
||||
elementName={"element1"}
|
||||
colorScheme="suggested"
|
||||
badge={`For crypto traders`}
|
||||
title={``}
|
||||
body={``}
|
||||
bullets={[
|
||||
{
|
||||
text: `Subscribe to the defi contracts you care about`,
|
||||
icon: FaFileContract,
|
||||
color: "suggested.50",
|
||||
bgColor: "suggested.900",
|
||||
},
|
||||
{
|
||||
text: `Make sense of how others are calling these contracts using Moonstream dashboards.
|
||||
`,
|
||||
icon: RiDashboardFill,
|
||||
color: "suggested.50",
|
||||
bgColor: "suggested.900",
|
||||
},
|
||||
{
|
||||
text: `Get data directly from the transaction pool through our global network of Ethereum nodes`,
|
||||
icon: GiMeshBall,
|
||||
color: "suggested.50",
|
||||
bgColor: "suggested.900",
|
||||
},
|
||||
]}
|
||||
imgURL={assets["cryptoTraders"]}
|
||||
/>
|
||||
</GridItem>
|
||||
<GridItem
|
||||
px="7%"
|
||||
colSpan="12"
|
||||
pt={["1rem", "1rem", "5.125rem", null, "5.125rem"]}
|
||||
pb={["0", "66px", null, "66px"]}
|
||||
id="algoFund"
|
||||
minH={ui.isMobileView ? "100vh" : null}
|
||||
>
|
||||
<SplitWithImage
|
||||
cta={{
|
||||
label: "I want early access!",
|
||||
onClick: () => {
|
||||
track(`${MIXPANEL_EVENTS.BUTTON_CLICKED}`, {
|
||||
[`${MIXPANEL_PROPS.BUTTON_CLICKED}`]: `Early access CTA: Algo fund`,
|
||||
});
|
||||
toggleModal("hubspot-fund");
|
||||
},
|
||||
}}
|
||||
elementName={"element2"}
|
||||
mirror={true}
|
||||
colorScheme="secondary"
|
||||
badge={`For algorithmic funds`}
|
||||
bullets={[
|
||||
{
|
||||
text: `Get API access to your stream`,
|
||||
icon: AiFillApi,
|
||||
color: "secondary.50",
|
||||
bgColor: "secondary.900",
|
||||
},
|
||||
{
|
||||
text: `Set conditions that trigger predefined actions`,
|
||||
icon: GiLogicGateXor,
|
||||
color: "secondary.50",
|
||||
bgColor: "secondary.900",
|
||||
},
|
||||
{
|
||||
text: `Execute transactions directly on Moonstream nodes`,
|
||||
icon: BiTransfer,
|
||||
color: "secondary.50",
|
||||
bgColor: "secondary.900",
|
||||
},
|
||||
]}
|
||||
imgURL={assets["algorithmicFunds"]}
|
||||
/>
|
||||
</GridItem>
|
||||
<GridItem
|
||||
px="7%"
|
||||
colSpan="12"
|
||||
pt={["1rem", "1rem", "5.125rem", null, "5.125rem"]}
|
||||
pb={["0", "66px", null, "66px"]}
|
||||
id="smartDeveloper"
|
||||
minH={ui.isMobileView ? "100vh" : null}
|
||||
>
|
||||
<SplitWithImage
|
||||
cta={{
|
||||
label: "I want early access!",
|
||||
onClick: () => {
|
||||
track(`${MIXPANEL_EVENTS.BUTTON_CLICKED}`, {
|
||||
[`${MIXPANEL_PROPS.BUTTON_CLICKED}`]: `Early access CTA: developer`,
|
||||
});
|
||||
toggleModal("hubspot-developer");
|
||||
},
|
||||
}}
|
||||
elementName={"element3"}
|
||||
colorScheme="primary"
|
||||
badge={`For smart contract developers`}
|
||||
bullets={[
|
||||
{
|
||||
text: `See how people use your smart contracts`,
|
||||
icon: IoTelescopeSharp,
|
||||
color: "primary.50",
|
||||
bgColor: "primary.900",
|
||||
},
|
||||
{
|
||||
text: `Set up alerts on suspicious activity`,
|
||||
icon: GiSuspicious,
|
||||
color: "primary.50",
|
||||
bgColor: "primary.900",
|
||||
},
|
||||
{
|
||||
text: `Register webhooks to connect your off-chain infrastructure`,
|
||||
icon: GiHook,
|
||||
color: "primary.50",
|
||||
bgColor: "primary.900",
|
||||
},
|
||||
]}
|
||||
imgURL={assets["smartDevelopers"]}
|
||||
/>
|
||||
</GridItem>
|
||||
<GridItem
|
||||
placeItems="center"
|
||||
w="100%"
|
||||
colSpan="12"
|
||||
pt={["0", "0", "5.125rem", null, "5.125rem"]}
|
||||
pb="120px"
|
||||
>
|
||||
<Center>
|
||||
<Button
|
||||
as={Link}
|
||||
isExternal
|
||||
href={"https://discord.gg/K56VNUQGvA"}
|
||||
size="lg"
|
||||
variant="solid"
|
||||
colorScheme="suggested"
|
||||
id="test"
|
||||
onClick={() => {
|
||||
track(`${MIXPANEL_EVENTS.BUTTON_CLICKED}`, {
|
||||
[`${MIXPANEL_PROPS.BUTTON_CLICKED}`]: `Join our discord`,
|
||||
});
|
||||
toggleModal("hubspot");
|
||||
}}
|
||||
>
|
||||
Join our discord
|
||||
</Button>
|
||||
</Center>
|
||||
</GridItem>
|
||||
</Grid>
|
||||
</Flex>
|
||||
</Box>
|
||||
</Fade>
|
||||
</Suspense>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -530,7 +574,4 @@ export async function getStaticProps() {
|
|||
};
|
||||
}
|
||||
|
||||
Homepage.layout = "default";
|
||||
Homepage.getLayout = getLayout;
|
||||
|
||||
export default Homepage;
|
||||
|
|
|
@ -1,19 +1,26 @@
|
|||
import React, {useContext} from "react";
|
||||
import { Flex, HStack, Skeleton, Box, Heading, Center, Spinner } from "@chakra-ui/react";
|
||||
import { useTxInfo, useTxCashe, useRouter } from "../../src/core/hooks";
|
||||
import React, { useContext } from "react";
|
||||
import {
|
||||
Flex,
|
||||
HStack,
|
||||
Skeleton,
|
||||
Box,
|
||||
Heading,
|
||||
Center,
|
||||
Spinner,
|
||||
} from "@chakra-ui/react";
|
||||
import { useTxInfo, useRouter } from "../../src/core/hooks";
|
||||
import FourOFour from "../../src/components/FourOFour";
|
||||
import FourOThree from "../../src/components/FourOThree";
|
||||
import Tags from "../../src/components/Tags";
|
||||
import { getLayout } from "../../src/layouts/EntriesLayout";
|
||||
import Scrollable from "../../src/components/Scrollable";
|
||||
import TxInfo from "../../src/components/TxInfo"
|
||||
import TxInfo from "../../src/components/TxInfo";
|
||||
import UIContext from "../../src/core/providers/UIProvider/context";
|
||||
|
||||
const Entry = () => {
|
||||
const ui = useContext(UIContext);
|
||||
const router = useRouter();
|
||||
const { entryId } = router.params;
|
||||
const txCache = useTxCashe;
|
||||
|
||||
const callReroute = () => {
|
||||
ui.setEntriesViewMode("list");
|
||||
|
@ -35,22 +42,20 @@ const Entry = () => {
|
|||
</Center>
|
||||
</Box>
|
||||
);
|
||||
return (
|
||||
<LoadingSpinner/>
|
||||
)
|
||||
}
|
||||
return <LoadingSpinner />;
|
||||
};
|
||||
|
||||
const transaction = txCache.getCurrentTransaction()
|
||||
|
||||
const {
|
||||
data: entry,
|
||||
isFetchedAfterMount,
|
||||
isLoading,
|
||||
isFetching, //If transaction.tx is undefined, will not fetch
|
||||
isError,
|
||||
error,
|
||||
} = useTxInfo({tx:transaction})
|
||||
|
||||
if (isError) {return callReroute()}
|
||||
} = useTxInfo({ tx: ui.currentTransaction });
|
||||
if (!isFetching) {
|
||||
return callReroute();
|
||||
}
|
||||
if (isError && error.response.status === 404) return <FourOFour />;
|
||||
if (isError && error.response.status === 403) return <FourOThree />;
|
||||
// if (!entry || isLoading) return "";
|
||||
|
@ -83,7 +88,7 @@ const Entry = () => {
|
|||
fontSize="1.5rem"
|
||||
textAlign="left"
|
||||
>
|
||||
{entry && entry.hash}
|
||||
{entry && entry.tx.hash}
|
||||
</Heading>
|
||||
</HStack>
|
||||
</Skeleton>
|
||||
|
@ -106,7 +111,7 @@ const Entry = () => {
|
|||
isLoaded={isFetchedAfterMount || entry}
|
||||
>
|
||||
<Scrollable>
|
||||
{!isLoading && (<TxInfo transaction = {entry}></TxInfo> )}
|
||||
{!isLoading && <TxInfo transaction={entry}></TxInfo>}
|
||||
</Scrollable>
|
||||
</Skeleton>
|
||||
</Flex>
|
||||
|
|
|
@ -30,7 +30,6 @@ const AccountIconButton = (props) => {
|
|||
zIndex="dropdown"
|
||||
width={["100vw", "100vw", "18rem", "20rem", "22rem", "24rem"]}
|
||||
borderRadius={0}
|
||||
m={0}
|
||||
>
|
||||
<MenuGroup>
|
||||
<RouterLink href="/account/security" passHref>
|
||||
|
|
|
@ -4,7 +4,6 @@ import {
|
|||
Flex,
|
||||
Button,
|
||||
Image,
|
||||
ButtonGroup,
|
||||
Text,
|
||||
IconButton,
|
||||
Link,
|
||||
|
@ -128,34 +127,6 @@ const AppNavbar = () => {
|
|||
</Fade>
|
||||
<Spacer />
|
||||
<Flex placeSelf="flex-end">
|
||||
<ButtonGroup
|
||||
alignSelf="center"
|
||||
// position="relative"
|
||||
left={
|
||||
isSearchBarActive
|
||||
? "100%"
|
||||
: ["64px", "30%", "50%", "55%", null, "60%"]
|
||||
}
|
||||
// hidden={ui.searchBarActive}
|
||||
display={isSearchBarActive ? "hidden" : "block"}
|
||||
variant="link"
|
||||
colorScheme="secondary"
|
||||
spacing={4}
|
||||
px={2}
|
||||
zIndex={ui.searchBarActive ? -10 : 0}
|
||||
size={["xs", "xs", "xs", "lg", null, "lg"]}
|
||||
>
|
||||
<RouterLink href="/pricing" passHref>
|
||||
<Button color="white" fontWeight="400">
|
||||
Pricing
|
||||
</Button>
|
||||
</RouterLink>
|
||||
<RouterLink href="/product" passHref>
|
||||
<Button color="white" fontWeight="400">
|
||||
Product
|
||||
</Button>
|
||||
</RouterLink>
|
||||
</ButtonGroup>
|
||||
<SupportPopover />
|
||||
<AccountIconButton
|
||||
colorScheme="primary"
|
||||
|
@ -256,7 +227,6 @@ const AppNavbar = () => {
|
|||
{!isSearchBarActive && (
|
||||
<AccountIconButton
|
||||
variant="link"
|
||||
mx={0}
|
||||
justifyContent="space-evenly"
|
||||
alignContent="center"
|
||||
h="32px"
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
import { React, useEffect, useState } from "react";
|
||||
import {
|
||||
Box,
|
||||
Popover,
|
||||
PopoverTrigger,
|
||||
PopoverContent,
|
||||
PopoverHeader,
|
||||
PopoverBody,
|
||||
PopoverFooter,
|
||||
PopoverArrow,
|
||||
PopoverCloseButton,
|
||||
Portal,
|
||||
Stack,
|
||||
IconButton,
|
||||
Text,
|
||||
Input,
|
||||
useDisclosure,
|
||||
Button,
|
||||
} from "@chakra-ui/react";
|
||||
import { makeColor } from "../core/utils/makeColor";
|
||||
import { BiRefresh } from "react-icons/bi";
|
||||
import { GithubPicker } from "react-color";
|
||||
|
||||
const ColorSelector = (props) => {
|
||||
const { onOpen, onClose, isOpen } = useDisclosure();
|
||||
const [color, setColor] = useState(props.initialColor ?? makeColor());
|
||||
const [triggerColor, setTriggerColor] = useState(color);
|
||||
|
||||
useEffect(() => {
|
||||
setTriggerColor(props.initialColor);
|
||||
}, [props.initialColor]);
|
||||
|
||||
const handleChangeColorComplete = (color) => {
|
||||
setColor(color.hex);
|
||||
};
|
||||
|
||||
const handleChangeColor = (event) => setColor(event.target.value);
|
||||
|
||||
return (
|
||||
<Popover isOpen={isOpen} onOpen={onOpen} onClose={onClose}>
|
||||
<PopoverTrigger>
|
||||
<Box
|
||||
placeSelf="center"
|
||||
boxSize="24px"
|
||||
borderRadius="sm"
|
||||
bgColor={triggerColor}
|
||||
></Box>
|
||||
</PopoverTrigger>
|
||||
<Portal>
|
||||
<PopoverContent bg={"white.100"}>
|
||||
<PopoverArrow />
|
||||
<PopoverHeader>Change color</PopoverHeader>
|
||||
<PopoverCloseButton />
|
||||
<PopoverBody>
|
||||
<Stack direction="row" pb={2}>
|
||||
<Text fontWeight="600" alignSelf="center">
|
||||
Label color
|
||||
</Text>{" "}
|
||||
<IconButton
|
||||
size="md"
|
||||
// colorScheme="primary"
|
||||
color={"white.100"}
|
||||
_hover={{ bgColor: { color } }}
|
||||
bgColor={color}
|
||||
variant="outline"
|
||||
onClick={() => setColor(makeColor())}
|
||||
icon={<BiRefresh />}
|
||||
/>
|
||||
<Input
|
||||
type="input"
|
||||
placeholder="color"
|
||||
name="color"
|
||||
value={color}
|
||||
onChange={handleChangeColor}
|
||||
w="200px"
|
||||
onSubmit={handleChangeColorComplete}
|
||||
></Input>
|
||||
</Stack>
|
||||
<GithubPicker
|
||||
// color={this.state.background}
|
||||
onChangeComplete={handleChangeColorComplete}
|
||||
/>
|
||||
</PopoverBody>
|
||||
<PopoverFooter>
|
||||
<Button
|
||||
onClick={() => {
|
||||
props.callback(color);
|
||||
onClose();
|
||||
}}
|
||||
colorScheme="suggested"
|
||||
variant="outline"
|
||||
>
|
||||
Apply
|
||||
</Button>
|
||||
</PopoverFooter>
|
||||
</PopoverContent>
|
||||
</Portal>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
||||
export default ColorSelector;
|
|
@ -14,13 +14,17 @@ import {
|
|||
Button,
|
||||
ModalFooter,
|
||||
Spinner,
|
||||
IconButton,
|
||||
} from "@chakra-ui/react";
|
||||
import RadioCard from "./RadioCard";
|
||||
import { useForm } from "react-hook-form";
|
||||
|
||||
import { GithubPicker } from "react-color";
|
||||
import { BiRefresh } from "react-icons/bi";
|
||||
import { makeColor } from "../core/utils/makeColor";
|
||||
const NewSubscription = ({ isFreeOption, onClose }) => {
|
||||
const [color, setColor] = useState(makeColor());
|
||||
const { typesCache, createSubscription } = useSubscriptions();
|
||||
const { handleSubmit, errors, register } = useForm();
|
||||
const { handleSubmit, errors, register } = useForm({});
|
||||
const [radioState, setRadioState] = useState("ethereum_blockchain");
|
||||
let { getRootProps, getRadioProps } = useRadioGroup({
|
||||
name: "type",
|
||||
|
@ -41,10 +45,15 @@ const NewSubscription = ({ isFreeOption, onClose }) => {
|
|||
const createSubscriptionWrap = (props) => {
|
||||
createSubscription.mutate({
|
||||
...props,
|
||||
color: color,
|
||||
type: isFreeOption ? "free" : radioState,
|
||||
});
|
||||
};
|
||||
|
||||
const handleChangeColorComplete = (color) => {
|
||||
setColor(color.hex);
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit(createSubscriptionWrap)}>
|
||||
<ModalHeader>Subscribe to a new address</ModalHeader>
|
||||
|
@ -83,7 +92,7 @@ const NewSubscription = ({ isFreeOption, onClose }) => {
|
|||
: `On which source?`}
|
||||
</Text>
|
||||
|
||||
<FormControl isInvalid={errors.type}>
|
||||
<FormControl isInvalid={errors.subscription_type}>
|
||||
<HStack {...group} alignItems="stretch">
|
||||
{typesCache.data.subscriptions.map((type) => {
|
||||
const radio = getRadioProps({
|
||||
|
@ -100,9 +109,54 @@ const NewSubscription = ({ isFreeOption, onClose }) => {
|
|||
);
|
||||
})}
|
||||
</HStack>
|
||||
<Input
|
||||
type="hidden"
|
||||
placeholder="subscription_type"
|
||||
name="subscription_type"
|
||||
ref={register({ required: "select type" })}
|
||||
value={radioState}
|
||||
onChange={() => null}
|
||||
></Input>
|
||||
<FormErrorMessage color="unsafe.400" pl="1">
|
||||
{errors.subscription_type && errors.subscription_type.message}
|
||||
</FormErrorMessage>
|
||||
</FormControl>
|
||||
</Stack>
|
||||
<Input placeholder="color" name="color" ref={register()}></Input>
|
||||
<FormControl isInvalid={errors.color}>
|
||||
<Stack direction="row" pb={2}>
|
||||
<Text fontWeight="600" alignSelf="center">
|
||||
Label color
|
||||
</Text>{" "}
|
||||
<IconButton
|
||||
size="md"
|
||||
// colorScheme="primary"
|
||||
color={"white.100"}
|
||||
_hover={{ bgColor: { color } }}
|
||||
bgColor={color}
|
||||
variant="outline"
|
||||
onClick={() => setColor(makeColor())}
|
||||
icon={<BiRefresh />}
|
||||
/>
|
||||
<Input
|
||||
type="input"
|
||||
placeholder="color"
|
||||
name="color"
|
||||
ref={register({ required: "color is required!" })}
|
||||
value={color}
|
||||
onChange={() => null}
|
||||
w="200px"
|
||||
></Input>
|
||||
</Stack>
|
||||
|
||||
<GithubPicker
|
||||
// color={this.state.background}
|
||||
onChangeComplete={handleChangeColorComplete}
|
||||
/>
|
||||
|
||||
<FormErrorMessage color="unsafe.400" pl="1">
|
||||
{errors.color && errors.color.message}
|
||||
</FormErrorMessage>
|
||||
</FormControl>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button
|
||||
|
@ -112,7 +166,9 @@ const NewSubscription = ({ isFreeOption, onClose }) => {
|
|||
>
|
||||
Confirm
|
||||
</Button>
|
||||
<Button colorScheme="gray">Cancel</Button>
|
||||
<Button colorScheme="gray" onClick={onClose}>
|
||||
Cancel
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</form>
|
||||
);
|
||||
|
|
|
@ -14,9 +14,9 @@ import moment from "moment";
|
|||
import { ArrowRightIcon } from "@chakra-ui/icons";
|
||||
import { useRouter } from "../core/hooks";
|
||||
import UIContext from "../core/providers/UIProvider/context";
|
||||
import { useToast, useTxCashe } from "../core/hooks";
|
||||
import { useToast } from "../core/hooks";
|
||||
|
||||
const StreamEntry = ({ entry, filterCallback, filterConstants }) => {
|
||||
const StreamEntry = ({ entry }) => {
|
||||
const ui = useContext(UIContext);
|
||||
const router = useRouter();
|
||||
const [copyString, setCopyString] = useState(false);
|
||||
|
@ -34,7 +34,7 @@ const StreamEntry = ({ entry, filterCallback, filterConstants }) => {
|
|||
const handleViewClicked = (entryId) => {
|
||||
ui.setEntryId(entryId);
|
||||
ui.setEntriesViewMode("entry");
|
||||
useTxCashe.setCurrentTransaction(entry);
|
||||
ui.setCurrentTransaction(entry);
|
||||
router.push({
|
||||
pathname: `/stream/${entry.hash}`,
|
||||
query: router.query,
|
||||
|
|
|
@ -17,13 +17,17 @@ import moment from "moment";
|
|||
import CopyButton from "./CopyButton";
|
||||
import { useSubscriptions } from "../core/hooks";
|
||||
import ConfirmationRequest from "./ConfirmationRequest";
|
||||
import ColorSelector from "./ColorSelector";
|
||||
|
||||
const SubscriptionsList = () => {
|
||||
const { subscriptionsCache, changeNote, deleteSubscription } =
|
||||
const { subscriptionsCache, updateSubscription, deleteSubscription } =
|
||||
useSubscriptions();
|
||||
|
||||
const updateCallback = ({ id, note }) => {
|
||||
changeNote.mutate({ id, note });
|
||||
const updateCallback = ({ id, label, color }) => {
|
||||
const data = { id: id };
|
||||
label && (data.label = label);
|
||||
color && (data.color = color);
|
||||
updateSubscription.mutate(data);
|
||||
};
|
||||
|
||||
if (subscriptionsCache.data) {
|
||||
|
@ -45,6 +49,7 @@ const SubscriptionsList = () => {
|
|||
<Th>Token</Th>
|
||||
<Th>Label</Th>
|
||||
<Th>Address</Th>
|
||||
<Th>Color</Th>
|
||||
<Th>Date Created</Th>
|
||||
<Th>Actions</Th>
|
||||
</Tr>
|
||||
|
@ -99,6 +104,15 @@ const SubscriptionsList = () => {
|
|||
<Td mr={4} p={0}>
|
||||
<CopyButton>{subscription.address}</CopyButton>
|
||||
</Td>
|
||||
<Td>
|
||||
<ColorSelector
|
||||
// subscriptionId={subscription.id}
|
||||
initialColor={subscription.color}
|
||||
callback={(color) =>
|
||||
updateCallback({ id: subscription.id, color: color })
|
||||
}
|
||||
/>
|
||||
</Td>
|
||||
<Td py={0}>{moment(subscription.created_at).format("L")}</Td>
|
||||
|
||||
<Td py={0}>
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
VStack,
|
||||
} from "@chakra-ui/react";
|
||||
import { Table, Thead, Tbody, Tr, Th, Td } from "@chakra-ui/react";
|
||||
|
||||
const toEth = (wei) => { return wei / Math.pow(10, 18) }
|
||||
const TxABI = (props) => {
|
||||
const byteCode = props.byteCode;
|
||||
const abi = props.abi;
|
||||
|
@ -58,17 +58,18 @@ const TxInfo = (props) => {
|
|||
<StatGroup>
|
||||
<Stat>
|
||||
<StatLabel>Value</StatLabel>
|
||||
<StatNumber>{transaction.tx.value}</StatNumber>
|
||||
<StatHelpText>amount of ETH to transfer in WEI</StatHelpText>
|
||||
<StatNumber>{toEth(transaction.tx.value)} eth</StatNumber>
|
||||
<StatHelpText>amount of ETH to transfer</StatHelpText>
|
||||
</Stat>
|
||||
<Stat>
|
||||
<StatLabel>Gas</StatLabel>
|
||||
<StatLabel>Gas limit</StatLabel>
|
||||
<StatNumber>{transaction.tx.gas}</StatNumber>
|
||||
<StatHelpText>gas limit for transaction</StatHelpText>
|
||||
<StatHelpText>Maximum amount of gas </StatHelpText>
|
||||
<StatHelpText>provided for the transaction</StatHelpText>
|
||||
</Stat>
|
||||
<Stat>
|
||||
<StatLabel>Gas price</StatLabel>
|
||||
<StatNumber>{transaction.tx.gasPrice}</StatNumber>
|
||||
<StatNumber>{toEth(transaction.tx.gasPrice)} eth</StatNumber>
|
||||
<StatHelpText>the fee the sender pays per unit of gas</StatHelpText>
|
||||
</Stat>
|
||||
</StatGroup>
|
||||
|
|
|
@ -20,5 +20,4 @@ export { default as useStripe } from "./useStripe";
|
|||
export { default as useSubscriptions } from "./useSubscriptions";
|
||||
export { default as useToast } from "./useToast";
|
||||
export { default as useTxInfo } from "./useTxInfo";
|
||||
export { default as useTxCashe } from "./useTxCache";
|
||||
export { default as useUser } from "./useUser";
|
||||
|
|
|
@ -50,12 +50,15 @@ const useSubscriptions = () => {
|
|||
}
|
||||
);
|
||||
|
||||
const changeNote = useMutation(SubscriptionsService.modifySubscription(), {
|
||||
onError: (error) => toast(error, "error"),
|
||||
onSuccess: () => {
|
||||
subscriptionsCache.refetch();
|
||||
},
|
||||
});
|
||||
const updateSubscription = useMutation(
|
||||
SubscriptionsService.modifySubscription(),
|
||||
{
|
||||
onError: (error) => toast(error, "error"),
|
||||
onSuccess: () => {
|
||||
subscriptionsCache.refetch();
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const deleteSubscription = useMutation(
|
||||
SubscriptionsService.deleteSubscription(),
|
||||
|
@ -71,7 +74,7 @@ const useSubscriptions = () => {
|
|||
createSubscription,
|
||||
subscriptionsCache,
|
||||
typesCache,
|
||||
changeNote,
|
||||
updateSubscription,
|
||||
deleteSubscription,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
class TxCashe {
|
||||
currentTransaction = undefined;
|
||||
getCurrentTransaction() {
|
||||
return this.currentTransaction;
|
||||
}
|
||||
setCurrentTransaction(transaction) {
|
||||
this.currentTransaction = transaction;
|
||||
}
|
||||
}
|
||||
const useTxCashe = new TxCashe();
|
||||
export default useTxCashe;
|
|
@ -4,27 +4,19 @@ import { queryCacheProps } from "./hookCommon";
|
|||
import { useToast } from ".";
|
||||
|
||||
const useTxInfo = (transaction) => {
|
||||
if (!transaction.tx)
|
||||
return {
|
||||
data: "undefined",
|
||||
isLoading: false,
|
||||
isFetchedAfterMount: true,
|
||||
refetch: false,
|
||||
isError: true,
|
||||
error: "undefined",
|
||||
};
|
||||
const toast = useToast();
|
||||
const getTxInfo = async () => {
|
||||
const response = await TxInfoService.getTxInfo(transaction);
|
||||
return response.data;
|
||||
};
|
||||
const { data, isLoading, isFetchedAfterMount, refetch, isError, error } =
|
||||
useQuery(["txinfo", transaction.tx.hash], getTxInfo, {
|
||||
useQuery(["txinfo", (transaction.tx && transaction.tx.hash)], getTxInfo, {
|
||||
...queryCacheProps,
|
||||
enabled: !!transaction.tx,
|
||||
onError: (error) => toast(error, "error"),
|
||||
});
|
||||
|
||||
return { data, isFetchedAfterMount, isLoading, refetch, isError, error };
|
||||
const isFetching = !!transaction.tx;
|
||||
return { data, isFetchedAfterMount, isLoading, refetch, isFetching, isError, error };
|
||||
};
|
||||
|
||||
export default useTxInfo;
|
||||
|
|
|
@ -28,7 +28,7 @@ const AnalyticsProvider = ({ children }) => {
|
|||
},
|
||||
{ transport: "sendBeacon" }
|
||||
);
|
||||
}, 1000);
|
||||
}, 30000);
|
||||
|
||||
return () => clearInterval(intervalId);
|
||||
// eslint-disable-next-line
|
||||
|
|
|
@ -149,6 +149,10 @@ const UIProvider = ({ children }) => {
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [router.params?.id]);
|
||||
|
||||
// *********** TX stream state **********************
|
||||
|
||||
const [currentTransaction, setCurrentTransaction] = useState(undefined);
|
||||
|
||||
// ********************************************************
|
||||
|
||||
return (
|
||||
|
@ -177,6 +181,8 @@ const UIProvider = ({ children }) => {
|
|||
entryId,
|
||||
setEntryId,
|
||||
sessionId,
|
||||
currentTransaction,
|
||||
setCurrentTransaction,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
|
|
@ -62,9 +62,10 @@ export const createSubscription =
|
|||
|
||||
export const modifySubscription =
|
||||
() =>
|
||||
({ id, note }) => {
|
||||
({ id, label, color }) => {
|
||||
const data = new FormData();
|
||||
data.append("note", note);
|
||||
color && data.append("color", color);
|
||||
label && data.append("label", label);
|
||||
data.append("id", id);
|
||||
return http({
|
||||
method: "POST",
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
export const makeColor = () => {
|
||||
var result = "#";
|
||||
var characters = "0123456789ABCDEF";
|
||||
var charactersLength = characters.length;
|
||||
for (var i = 0; i < 6; i++) {
|
||||
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||
}
|
||||
return result;
|
||||
};
|
|
@ -0,0 +1,81 @@
|
|||
/* Make clicks pass-through */
|
||||
#nprogress {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#nprogress .bar {
|
||||
background: #fd5602;
|
||||
|
||||
position: fixed;
|
||||
z-index: 1031;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
width: 100%;
|
||||
height: 3px;
|
||||
}
|
||||
|
||||
/* Fancy blur effect */
|
||||
#nprogress .peg {
|
||||
display: block;
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
width: 100px;
|
||||
height: 100%;
|
||||
box-shadow: 0 0 10px #fd5602, 0 0 5px #fd5602;
|
||||
opacity: 1;
|
||||
|
||||
-webkit-transform: rotate(3deg) translate(0px, -4px);
|
||||
-ms-transform: rotate(3deg) translate(0px, -4px);
|
||||
transform: rotate(3deg) translate(0px, -4px);
|
||||
}
|
||||
|
||||
/* Remove these to get rid of the spinner */
|
||||
#nprogress .spinner {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 1031;
|
||||
top: 15px;
|
||||
right: 15px;
|
||||
}
|
||||
|
||||
#nprogress .spinner-icon {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
box-sizing: border-box;
|
||||
|
||||
border: solid 2px transparent;
|
||||
border-top-color: #29d;
|
||||
border-left-color: #29d;
|
||||
border-radius: 50%;
|
||||
|
||||
-webkit-animation: nprogress-spinner 400ms linear infinite;
|
||||
animation: nprogress-spinner 400ms linear infinite;
|
||||
}
|
||||
|
||||
.nprogress-custom-parent {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nprogress-custom-parent #nprogress .spinner,
|
||||
.nprogress-custom-parent #nprogress .bar {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
@-webkit-keyframes nprogress-spinner {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@keyframes nprogress-spinner {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
|
@ -977,6 +977,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.2.0.tgz#f3933a44e365864f4dad5db94158106d511e8131"
|
||||
integrity sha512-sqKVVVOe5ivCaXDWivIJYVSaEgdQK9ul7a4Kity5Iw7u9+wBAPbX1RMSnLLmp7O4Vzj0WOWwMAJsTL00xwaNug==
|
||||
|
||||
"@icons/material@^0.2.4":
|
||||
version "0.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@icons/material/-/material-0.2.4.tgz#e90c9f71768b3736e76d7dd6783fc6c2afa88bc8"
|
||||
integrity sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==
|
||||
|
||||
"@jest/types@^26.6.2":
|
||||
version "26.6.2"
|
||||
resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e"
|
||||
|
@ -2565,6 +2570,11 @@ focus-lock@^0.8.1:
|
|||
dependencies:
|
||||
tslib "^1.9.3"
|
||||
|
||||
focus-visible@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/focus-visible/-/focus-visible-5.2.0.tgz#3a9e41fccf587bd25dcc2ef045508284f0a4d6b3"
|
||||
integrity sha512-Rwix9pBtC1Nuy5wysTmKy+UjbDJpIfg8eHjw0rjZ1mX4GNLz1Bmd16uDpI3Gk1i70Fgcs8Csg2lPm8HULFg9DQ==
|
||||
|
||||
follow-redirects@^1.10.0:
|
||||
version "1.14.1"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.1.tgz#d9114ded0a1cfdd334e164e6662ad02bfd91ff43"
|
||||
|
@ -3197,6 +3207,11 @@ locate-path@^5.0.0:
|
|||
dependencies:
|
||||
p-locate "^4.1.0"
|
||||
|
||||
lodash-es@^4.17.15:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
|
||||
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
|
||||
|
||||
lodash.clonedeep@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
|
||||
|
@ -3222,7 +3237,7 @@ lodash.truncate@^4.4.2:
|
|||
resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
|
||||
integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=
|
||||
|
||||
lodash@^4.17.13, lodash@^4.17.21, lodash@^4.17.4:
|
||||
lodash@^4.0.1, lodash@^4.17.13, lodash@^4.17.15, lodash@^4.17.21, lodash@^4.17.4:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
|
@ -3261,6 +3276,11 @@ match-sorter@^6.0.2:
|
|||
"@babel/runtime" "^7.12.5"
|
||||
remove-accents "0.4.2"
|
||||
|
||||
material-colors@^1.2.1:
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/material-colors/-/material-colors-1.2.6.tgz#6d1958871126992ceecc72f4bcc4d8f010865f46"
|
||||
integrity sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==
|
||||
|
||||
md5.js@^1.3.4:
|
||||
version "1.3.5"
|
||||
resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
|
||||
|
@ -3489,6 +3509,11 @@ normalize-path@^3.0.0, normalize-path@~3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
||||
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
|
||||
|
||||
nprogress@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/nprogress/-/nprogress-0.2.0.tgz#cb8f34c53213d895723fcbab907e9422adbcafb1"
|
||||
integrity sha1-y480xTIT2JVyP8urkH6UIq28r7E=
|
||||
|
||||
object-assign@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
|
@ -3834,7 +3859,7 @@ progress@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
|
||||
integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
|
||||
|
||||
prop-types@15.7.2, prop-types@^15.5.4, prop-types@^15.5.8, prop-types@^15.6.2, prop-types@^15.7.2:
|
||||
prop-types@15.7.2, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.8, prop-types@^15.6.2, prop-types@^15.7.2:
|
||||
version "15.7.2"
|
||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
|
||||
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
|
||||
|
@ -3934,6 +3959,19 @@ react-clientside-effect@^1.2.2:
|
|||
dependencies:
|
||||
"@babel/runtime" "^7.12.13"
|
||||
|
||||
react-color@^2.19.3:
|
||||
version "2.19.3"
|
||||
resolved "https://registry.yarnpkg.com/react-color/-/react-color-2.19.3.tgz#ec6c6b4568312a3c6a18420ab0472e146aa5683d"
|
||||
integrity sha512-LEeGE/ZzNLIsFWa1TMe8y5VYqr7bibneWmvJwm1pCn/eNmrabWDh659JSPn9BuaMpEfU83WTOJfnCcjDZwNQTA==
|
||||
dependencies:
|
||||
"@icons/material" "^0.2.4"
|
||||
lodash "^4.17.15"
|
||||
lodash-es "^4.17.15"
|
||||
material-colors "^1.2.1"
|
||||
prop-types "^15.5.10"
|
||||
reactcss "^1.2.0"
|
||||
tinycolor2 "^1.4.1"
|
||||
|
||||
react-copy-to-clipboard@^5.0.2:
|
||||
version "5.0.3"
|
||||
resolved "https://registry.yarnpkg.com/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.3.tgz#2a0623b1115a1d8c84144e9434d3342b5af41ab4"
|
||||
|
@ -4101,6 +4139,13 @@ react@^17.0.2:
|
|||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
reactcss@^1.2.0:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/reactcss/-/reactcss-1.2.3.tgz#c00013875e557b1cf0dfd9a368a1c3dab3b548dd"
|
||||
integrity sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==
|
||||
dependencies:
|
||||
lodash "^4.0.1"
|
||||
|
||||
read-pkg-up@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07"
|
||||
|
@ -4673,7 +4718,7 @@ tiny-invariant@^1.0.6:
|
|||
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875"
|
||||
integrity sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==
|
||||
|
||||
tinycolor2@1.4.2:
|
||||
tinycolor2@1.4.2, tinycolor2@^1.4.1:
|
||||
version "1.4.2"
|
||||
resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.2.tgz#3f6a4d1071ad07676d7fa472e1fac40a719d8803"
|
||||
integrity sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==
|
||||
|
|
Ładowanie…
Reference in New Issue