Merge branch 'main' into ethscan-crawler

pull/93/head
yhtiyar 2021-08-09 17:46:57 +03:00
commit b3e3c0d85f
13 zmienionych plików z 416 dodań i 385 usunięć

Wyświetl plik

@ -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
```

Wyświetl plik

@ -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(
@ -218,6 +216,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,

Wyświetl plik

@ -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]]:

Wyświetl plik

@ -2,4 +2,4 @@
Moonstream crawlers version.
"""
MOONSTREAMCRAWLERS_VERSION = "0.0.1"
MOONCRAWL_VERSION = "0.0.2"

Wyświetl plik

@ -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",
@ -40,7 +40,5 @@ setup(
"boto3",
],
extras_require={"dev": ["black", "mypy", "types-requests"]},
entry_points={
"console_scripts": ["moonstreamcrawlers=moonstreamcrawlers.cli:main"]
},
entry_points={"console_scripts": ["mooncrawl=mooncrawl.cli:main"]},
)

Wyświetl plik

@ -26,6 +26,9 @@ 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 UIContext from "../src/core/providers/UIProvider/context";
const SplitWithImage = dynamic(
() => import("../src/components/SplitWithImage"),
{
@ -38,14 +41,7 @@ const ConnectedButtons = dynamic(
ssr: false,
}
);
const UIContext = dynamic(
() => import("../src/core/providers/UIProvider/context"),
{
ssr: false,
}
);
import { MIXPANEL_PROPS } from "../src/core/providers/AnalyticsProvider/constants";
const RiDashboardFill = dynamic(() =>
import("react-icons/ri").then((mod) => mod.RiDashboardFill)
);
@ -202,349 +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, "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 Musks 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>
<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 Musks 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>
);
};

Wyświetl plik

@ -118,7 +118,7 @@ const NewSubscription = ({ isFreeOption, onClose }) => {
onChange={() => null}
></Input>
<FormErrorMessage color="unsafe.400" pl="1">
{errors.subscription_type_ && errors.subscription_type_.message}
{errors.subscription_type && errors.subscription_type.message}
</FormErrorMessage>
</FormControl>
</Stack>