Merge branch 'main' into go-txpool-crawler

pull/138/head
kompotkot 2021-08-24 15:57:55 +00:00
commit d14be3e5d8
44 zmienionych plików z 1530 dodań i 735 usunięć

Wyświetl plik

@ -19,9 +19,9 @@ jobs:
- name: Install test requirements
working-directory: ./backend
run: pip install -r requirements.txt
# - name: Mypy type check
# working-directory: ./backend
# run: mypy moonstream/
- name: Mypy type check
working-directory: ./backend
run: mypy moonstream/
- name: Black syntax check
working-directory: ./backend
run: black --check moonstream/

Wyświetl plik

@ -19,9 +19,9 @@ jobs:
- name: Install test requirements
working-directory: ./crawlers/mooncrawl
run: pip install -e .[dev]
# - name: Mypy type check
# working-directory: ./crawlers
# run: mypy mooncrawl/
- name: Mypy type check
working-directory: ./crawlers
run: mypy mooncrawl/
- name: Black syntax check
working-directory: ./crawlers/mooncrawl
run: black --check mooncrawl/

Wyświetl plik

@ -19,9 +19,9 @@ jobs:
- name: Install test requirements
working-directory: ./db
run: pip install -e .[dev]
# - name: Mypy type check
# working-directory: ./db
# run: mypy moonstreamdb/
- name: Mypy type check
working-directory: ./db
run: mypy moonstreamdb/
- name: Black syntax check
working-directory: ./db
run: black --check moonstreamdb/

Wyświetl plik

@ -1,14 +1,11 @@
from datetime import datetime
import json
import logging
from typing import Dict, Any, List, Optional
from typing import Dict, Any, List, Optional, Union
from sqlalchemy.engine.base import Transaction
import boto3 # type: ignore
from moonstreamdb.models import (
EthereumBlock,
EthereumTransaction,
EthereumPendingTransaction,
EthereumAddress,
EthereumLabel,
)
@ -16,9 +13,7 @@ from sqlalchemy import or_, and_, text
from sqlalchemy.orm import Session
from . import data
from .settings import DEFAULT_STREAM_TIMEINTERVAL
from .settings import DEFAULT_STREAM_TIMEINTERVAL, ETHERSCAN_SMARTCONTRACTS_BUCKET
logger = logging.getLogger(__name__)
@ -263,9 +258,43 @@ def parse_search_query_to_sqlalchemy_filters(q: str, allowed_addresses: List[str
return constructed_filters
def get_source_code(
db_session: Session, contract_address: str
) -> Optional[data.EthereumSmartContractSourceInfo]:
query = db_session.query(EthereumAddress.id).filter(
EthereumAddress.address == contract_address
)
id = query.one_or_none()
if id is None:
return None
labels = (
db_session.query(EthereumLabel).filter(EthereumLabel.address_id == id[0]).all()
)
for label in labels:
if label.label == "etherscan_smartcontract":
object_uri = label.label_data["object_uri"]
key = object_uri.split("s3://etherscan-smart-contracts/")[1]
s3 = boto3.client("s3")
bucket = ETHERSCAN_SMARTCONTRACTS_BUCKET
try:
raw_obj = s3.get_object(Bucket=bucket, Key=key)
obj_data = json.loads(raw_obj["Body"].read().decode("utf-8"))["data"]
contract_source_info = data.EthereumSmartContractSourceInfo(
name=obj_data["ContractName"],
source_code=obj_data["SourceCode"],
compiler_version=obj_data["CompilerVersion"],
abi=obj_data["ABI"],
)
return contract_source_info
except:
logger.error(f"Failed to load smart contract {contract_address}")
return None
def get_address_labels(
db_session: Session, start: int, limit: int, addresses: Optional[List[str]] = None
) -> List[EthereumAddress]:
db_session: Session, start: int, limit: int, addresses: Optional[str] = None
) -> data.AddressListLabelsResponse:
"""
Attach labels to addresses.
"""

Wyświetl plik

@ -133,11 +133,19 @@ class TxinfoEthereumBlockchainRequest(BaseModel):
tx: EthereumTransaction
class EthereumSmartContractSourceInfo(BaseModel):
name: str
source_code: str
abi: str
compiler_version: str
class TxinfoEthereumBlockchainResponse(BaseModel):
tx: EthereumTransaction
is_smart_contract_deployment: bool = False
is_smart_contract_call: bool = False
smart_contract_address: Optional[str] = None
smart_contract_info: Optional[EthereumSmartContractSourceInfo] = None
abi: Optional[ContractABI] = None
errors: List[str] = Field(default_factory=list)

Wyświetl plik

@ -8,6 +8,8 @@ end users.
import logging
from typing import Dict, Optional
from sqlalchemy.sql.expression import true
from fastapi import FastAPI, Depends, HTTPException, Query
from fastapi.middleware.cors import CORSMiddleware
from moonstreamdb.db import yield_db_session
@ -71,19 +73,22 @@ async def txinfo_ethereum_blockchain_handler(
logger.error(err)
response.errors.append("Could not decode ABI from the given input")
smart_contract = (
db_session.query(EthereumAddress)
.filter(EthereumAddress.transaction_hash == txinfo_request.tx.hash)
.one_or_none()
)
if smart_contract is not None:
response.smart_contract_address = smart_contract.address
if txinfo_request.tx.to_address is None:
# transaction is contract deployment:
if txinfo_request.tx.to_address is None:
response.is_smart_contract_deployment = True
smart_contract = (
db_session.query(EthereumAddress)
.filter(EthereumAddress.transaction_hash == txinfo_request.tx.hash)
.one_or_none()
)
if smart_contract is not None:
response.is_smart_contract_deployment = True
elif txinfo_request.tx.to_address == smart_contract.address:
response.is_smart_contract_call = True
else:
response.smart_contract_info = actions.get_source_code(
db_session, txinfo_request.tx.to_address
)
response.smart_contract_address = txinfo_request.tx.to_address
response.is_smart_contract_call = True
return response
@ -92,8 +97,8 @@ async def txinfo_ethereum_blockchain_handler(
)
async def addresses_labels_handler(
addresses: Optional[str] = Query(None),
start: Optional[int] = Query(0),
limit: Optional[int] = Query(100),
start: int = Query(0),
limit: int = Query(100),
db_session: Session = Depends(yield_db_session),
) -> data.AddressListLabelsResponse:
"""
@ -105,11 +110,11 @@ async def addresses_labels_handler(
status_code=406, detail="The limit cannot exceed 100 addresses"
)
try:
addresses = actions.get_address_labels(
addresses_response = actions.get_address_labels(
db_session=db_session, start=start, limit=limit, addresses=addresses
)
except Exception as err:
logger.error(f"Unable to get info about Ethereum addresses {err}")
raise HTTPException(status_code=500)
return addresses
return addresses_response

Wyświetl plik

@ -16,8 +16,8 @@ MOONSTREAM_DATA_JOURNAL_ID = os.environ.get("MOONSTREAM_DATA_JOURNAL_ID")
if MOONSTREAM_DATA_JOURNAL_ID is None:
raise ValueError("MOONSTREAM_DATA_JOURNAL_ID environment variable must be set")
MOONSTREAM_ADMIN_ACCESS_TOKEN = os.environ.get("MOONSTREAM_ADMIN_ACCESS_TOKEN")
if MOONSTREAM_ADMIN_ACCESS_TOKEN is None:
MOONSTREAM_ADMIN_ACCESS_TOKEN = os.environ.get("MOONSTREAM_ADMIN_ACCESS_TOKEN", "")
if MOONSTREAM_ADMIN_ACCESS_TOKEN == "":
raise ValueError("MOONSTREAM_ADMIN_ACCESS_TOKEN environment variable must be set")
# Origin
@ -41,3 +41,6 @@ for path in MOONSTREAM_OPENAPI_LIST:
DOCS_PATHS[f"/{path}/{DOCS_TARGET_PATH}/openapi.json"] = "GET"
DEFAULT_STREAM_TIMEINTERVAL = 5 * 60
# S3 Bucket
ETHERSCAN_SMARTCONTRACTS_BUCKET = "etherscan-smart-contracts"

Wyświetl plik

@ -91,6 +91,8 @@ 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(args.confirmations)
if bottom_block_number is None:
raise ValueError("Variable bottom_block_number can't be None")
bottom_block_number = max(bottom_block_number + 1, starting_block)
if bottom_block_number >= top_block_number:
print(

Wyświetl plik

@ -44,9 +44,11 @@ def connect(web3_uri: Optional[str] = MOONSTREAM_IPC_PATH):
return web3_client
def add_block(db_session, block: BlockData) -> None:
def add_block(db_session, block: Any) -> None:
"""
Add block if doesn't presented in database.
block: web3.types.BlockData
"""
block_obj = EthereumBlock(
block_number=block.number,
@ -70,9 +72,11 @@ def add_block(db_session, block: BlockData) -> None:
db_session.add(block_obj)
def add_block_transactions(db_session, block: BlockData) -> None:
def add_block_transactions(db_session, block: Any) -> None:
"""
Add block transactions.
block: web3.types.BlockData
"""
for tx in block.transactions:
tx_obj = EthereumTransaction(
@ -188,7 +192,7 @@ def crawl_blocks_executor(
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] = []
errors: List[BaseException] = []
def record_error(f: Future) -> None:
error = f.exception()
@ -196,7 +200,7 @@ def crawl_blocks_executor(
errors.append(error)
worker_indices = range(MOONSTREAM_CRAWL_WORKERS)
worker_job_lists = [[] for _ in worker_indices]
worker_job_lists: List[List[Any]] = [[] for _ in worker_indices]
for i, block_number in enumerate(block_numbers_list):
worker_job_lists[i % MOONSTREAM_CRAWL_WORKERS].append(block_number)
@ -290,6 +294,7 @@ def trending(
end_timestamp = int(date_range.end_time.timestamp())
def make_query(
db_session: Session,
identifying_column: Column,
statistic_column: Column,
aggregate_func: Callable,
@ -328,6 +333,7 @@ def trending(
try:
transactions_out_query = make_query(
db_session,
EthereumTransaction.from_address,
EthereumTransaction.hash,
func.count,
@ -339,6 +345,7 @@ def trending(
]
transactions_in_query = make_query(
db_session,
EthereumTransaction.to_address,
EthereumTransaction.hash,
func.count,
@ -350,6 +357,7 @@ def trending(
]
value_out_query = make_query(
db_session,
EthereumTransaction.from_address,
EthereumTransaction.value,
func.sum,
@ -361,6 +369,7 @@ def trending(
]
value_in_query = make_query(
db_session,
EthereumTransaction.to_address,
EthereumTransaction.value,
func.sum,

Wyświetl plik

@ -1,21 +1,22 @@
import argparse
import boto3
import sys
import time
from datetime import datetime
from typing import Any, List, Optional, Dict
from dataclasses import dataclass
import csv
import codecs
import json
import os
from sqlalchemy.orm import Session
import boto3 # type: ignore
from moonstreamdb.db import yield_db_session_ctx
import sys
import time
from datetime import datetime
from typing import Any, List, Optional, Tuple, Dict
from dataclasses import dataclass
from sqlalchemy.sql.expression import label, text
from .version import MOONCRAWL_VERSION
from moonstreamdb.models import EthereumAddress, EthereumLabel
import requests
from sqlalchemy.orm import Session
from sqlalchemy.sql.expression import text
from .version import MOONCRAWL_VERSION
from .settings import MOONSTREAM_ETHERSCAN_TOKEN
if MOONSTREAM_ETHERSCAN_TOKEN is None:

Wyświetl plik

@ -1,13 +1,13 @@
import unittest
from . import cli
from . import ethcrawler
class TestYieldBlockNumbersLists(unittest.TestCase):
def test_yield_descending_10_6_step_4(self):
partition = [
block_numbers_list
for block_numbers_list in cli.yield_blocks_numbers_lists(
for block_numbers_list in ethcrawler.yield_blocks_numbers_lists(
"10-6", block_step=4
)
]
@ -16,7 +16,7 @@ class TestYieldBlockNumbersLists(unittest.TestCase):
def test_yield_descending_10_6_step_3(self):
partition = [
block_numbers_list
for block_numbers_list in cli.yield_blocks_numbers_lists(
for block_numbers_list in ethcrawler.yield_blocks_numbers_lists(
"10-6", block_step=3
)
]
@ -25,8 +25,8 @@ class TestYieldBlockNumbersLists(unittest.TestCase):
def test_yield_descending_10_6_descending_step_3(self):
partition = [
block_numbers_list
for block_numbers_list in cli.yield_blocks_numbers_lists(
"10-6", cli.ProcessingOrder.DESCENDING, 3
for block_numbers_list in ethcrawler.yield_blocks_numbers_lists(
"10-6", ethcrawler.ProcessingOrder.DESCENDING, 3
)
]
self.assertListEqual(partition, [[10, 9, 8], [7, 6]])
@ -34,8 +34,8 @@ class TestYieldBlockNumbersLists(unittest.TestCase):
def test_yield_descending_10_6_descending_step_10(self):
partition = [
block_numbers_list
for block_numbers_list in cli.yield_blocks_numbers_lists(
"10-6", cli.ProcessingOrder.DESCENDING, 10
for block_numbers_list in ethcrawler.yield_blocks_numbers_lists(
"10-6", ethcrawler.ProcessingOrder.DESCENDING, 10
)
]
self.assertListEqual(partition, [[10, 9, 8, 7, 6]])
@ -43,7 +43,7 @@ class TestYieldBlockNumbersLists(unittest.TestCase):
def test_yield_descending_6_10_step_4(self):
partition = [
block_numbers_list
for block_numbers_list in cli.yield_blocks_numbers_lists(
for block_numbers_list in ethcrawler.yield_blocks_numbers_lists(
"6-10", block_step=4
)
]
@ -52,7 +52,7 @@ class TestYieldBlockNumbersLists(unittest.TestCase):
def test_yield_descending_6_10_step_3(self):
partition = [
block_numbers_list
for block_numbers_list in cli.yield_blocks_numbers_lists(
for block_numbers_list in ethcrawler.yield_blocks_numbers_lists(
"6-10", block_step=3
)
]
@ -61,8 +61,8 @@ class TestYieldBlockNumbersLists(unittest.TestCase):
def test_yield_descending_6_10_descending_step_3(self):
partition = [
block_numbers_list
for block_numbers_list in cli.yield_blocks_numbers_lists(
"6-10", cli.ProcessingOrder.DESCENDING, 3
for block_numbers_list in ethcrawler.yield_blocks_numbers_lists(
"6-10", ethcrawler.ProcessingOrder.DESCENDING, 3
)
]
self.assertListEqual(partition, [[10, 9, 8], [7, 6]])
@ -70,8 +70,8 @@ class TestYieldBlockNumbersLists(unittest.TestCase):
def test_yield_descending_6_10_descending_step_10(self):
partition = [
block_numbers_list
for block_numbers_list in cli.yield_blocks_numbers_lists(
"6-10", cli.ProcessingOrder.DESCENDING, 10
for block_numbers_list in ethcrawler.yield_blocks_numbers_lists(
"6-10", ethcrawler.ProcessingOrder.DESCENDING, 10
)
]
self.assertListEqual(partition, [[10, 9, 8, 7, 6]])
@ -79,8 +79,8 @@ class TestYieldBlockNumbersLists(unittest.TestCase):
def test_yield_ascending_10_6_ascending_step_3(self):
partition = [
block_numbers_list
for block_numbers_list in cli.yield_blocks_numbers_lists(
"10-6", cli.ProcessingOrder.ASCENDING, 3
for block_numbers_list in ethcrawler.yield_blocks_numbers_lists(
"10-6", ethcrawler.ProcessingOrder.ASCENDING, 3
)
]
self.assertListEqual(partition, [[6, 7, 8], [9, 10]])
@ -88,8 +88,8 @@ class TestYieldBlockNumbersLists(unittest.TestCase):
def test_yield_ascending_10_6_ascending_step_10(self):
partition = [
block_numbers_list
for block_numbers_list in cli.yield_blocks_numbers_lists(
"10-6", cli.ProcessingOrder.ASCENDING, 10
for block_numbers_list in ethcrawler.yield_blocks_numbers_lists(
"10-6", ethcrawler.ProcessingOrder.ASCENDING, 10
)
]
self.assertListEqual(partition, [[6, 7, 8, 9, 10]])
@ -97,8 +97,8 @@ class TestYieldBlockNumbersLists(unittest.TestCase):
def test_yield_ascending_6_10_ascending_step_4(self):
partition = [
block_numbers_list
for block_numbers_list in cli.yield_blocks_numbers_lists(
"6-10", cli.ProcessingOrder.ASCENDING, 4
for block_numbers_list in ethcrawler.yield_blocks_numbers_lists(
"6-10", ethcrawler.ProcessingOrder.ASCENDING, 4
)
]
self.assertListEqual(partition, [[6, 7, 8, 9], [10]])
@ -106,8 +106,8 @@ class TestYieldBlockNumbersLists(unittest.TestCase):
def test_yield_ascending_6_10_ascending_step_10(self):
partition = [
block_numbers_list
for block_numbers_list in cli.yield_blocks_numbers_lists(
"6-10", cli.ProcessingOrder.ASCENDING, 10
for block_numbers_list in ethcrawler.yield_blocks_numbers_lists(
"6-10", ethcrawler.ProcessingOrder.ASCENDING, 10
)
]
self.assertListEqual(partition, [[6, 7, 8, 9, 10]])

Wyświetl plik

@ -40,7 +40,9 @@ setup(
"web3",
"boto3",
],
extras_require={"dev": ["black", "mypy", "types-requests"]},
extras_require={
"dev": ["black", "mypy", "types-requests", "types-python-dateutil"]
},
entry_points={
"console_scripts": [
"ethcrawler=mooncrawl.ethcrawler:main",

Wyświetl plik

@ -19,6 +19,7 @@ import {
SimpleGrid,
useMediaQuery,
Grid,
Text,
GridItem,
} from "@chakra-ui/react";
import dynamic from "next/dynamic";
@ -28,7 +29,6 @@ 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"),
{
@ -244,17 +244,21 @@ const Homepage = () => {
textAlign="center"
alignItems="center"
spacing={6}
maxW="1620px"
maxW={["1620px", null, null, null, "1620px", "2222px"]}
px="7%"
h="100%"
pt={["10vh", null, "20vh"]}
>
<Heading size="2xl" fontWeight="semibold" color="white">
<Heading
fontSize={["lg", "4xl", "5xl", "5xl", "5xl", "6xl"]}
fontWeight="semibold"
color="white"
>
All the crypto data you care about in a single stream
</Heading>
<chakra.span
my={12}
fontSize={["lg", null, "xl"]}
fontSize={["md", "2xl", "3xl", "3xl", "3xl", "4xl"]}
display="inline-block"
color="primary.200"
>
@ -263,7 +267,7 @@ const Homepage = () => {
pool to Elon Musks latest tweets.
</chakra.span>
<chakra.span
fontSize={["lg", null, "xl"]}
fontSize={["md", "2xl", "3xl", "3xl", "3xl", "4xl"]}
display="inline-block"
color="primary.300"
>
@ -279,18 +283,44 @@ const Homepage = () => {
<GridItem
px="7%"
colSpan="12"
pt={["20px", "20px", "100px", null, "120px"]}
// pt={["20px", "20px", "100px", null, "120px"]}
pt={0}
pb={["20px", "56px", null, "184px"]}
minH="100vh"
>
<chakra.span
// {...HEADING_PROPS}
textAlign="center"
fontWeight="600"
fontSize="lg"
w="100%"
h="fit-content"
>
<Text
mb={18}
// mb={[12, 12, 12, null, 48]}
fontSize={["md", "2xl", "3xl", "3xl", "3xl", "4xl"]}
>
{` We believe in financial inclusion. Proprietary technologies
are not financially inclusive. That's why all our software
is `}
<chakra.span
display="inline-block"
textColor="secondary.900"
>
<i>open source</i>
</chakra.span>
</Text>
</chakra.span>
<Heading
{...HEADING_PROPS}
textAlign="center"
mt={16}
pb={[12, 12, 12, null, 48]}
>
Data you can add to your stream:
</Heading>
<SimpleGrid columns={[1, 2, 2, 4, null, 4]}>
<Stack spacing={1} px={1} alignItems="center">
<ChakraImage
@ -486,6 +516,16 @@ const Homepage = () => {
toggleModal("hubspot-developer");
},
}}
socialButton={{
url: "https://github.com/bugout-dev/moonstream/",
network: "github",
label: "See our github",
onClick: () => {
track(`${MIXPANEL_EVENTS.BUTTON_CLICKED}`, {
[`${MIXPANEL_PROPS.BUTTON_CLICKED}`]: `Github link in landing page`,
});
},
}}
elementName={"element3"}
colorScheme="primary"
badge={`For smart contract developers`}

Wyświetl plik

@ -0,0 +1,268 @@
import React, { useEffect, useState, useLayoutEffect } from "react";
import {
Heading,
Text,
Flex,
Link,
Stack,
chakra,
useMediaQuery,
UnorderedList,
ListItem,
useBreakpointValue,
} from "@chakra-ui/react";
import { DEFAULT_METATAGS } from "../../src/core/constants";
export async function getStaticProps() {
return {
props: { metaTags: { ...DEFAULT_METATAGS } },
};
}
const AWS_PATH =
"https://s3.amazonaws.com/static.simiotics.com/moonstream/assets";
const assets = {
background720: `${AWS_PATH}/product-background-720x405.png`,
background1920: `${AWS_PATH}/product-background-720x405.png`,
background2880: `${AWS_PATH}/product-background-720x405.png`,
background3840: `${AWS_PATH}/product-background-720x405.png`,
};
const Product = () => {
const [background, setBackground] = useState("background720");
const [backgroundLoaded720, setBackgroundLoaded720] = useState(false);
const [backgroundLoaded1920, setBackgroundLoaded1920] = useState(false);
const [backgroundLoaded2880, setBackgroundLoaded2880] = useState(false);
const [backgroundLoaded3840, setBackgroundLoaded3840] = useState(false);
const [
isLargerThan720px,
isLargerThan1920px,
isLargerThan2880px,
isLargerThan3840px,
] = useMediaQuery([
"(min-width: 720px)",
"(min-width: 1920px)",
"(min-width: 2880px)",
"(min-width: 3840px)",
]);
useEffect(() => {
assets["background720"] = `${AWS_PATH}/product-background-720x405.png`;
assets["background1920"] = `${AWS_PATH}/product-background-1920x1080.png`;
assets["background2880"] = `${AWS_PATH}/product-background-2880x1620.png`;
assets["background3840"] = `${AWS_PATH}/product-background-3840x2160.png`;
}, []);
useLayoutEffect(() => {
if (backgroundLoaded3840) {
setBackground("background3840");
} else if (backgroundLoaded2880) {
setBackground("background2880");
} else if (backgroundLoaded1920) {
setBackground("background1920");
} else {
setBackground("background720");
}
}, [
isLargerThan720px,
isLargerThan1920px,
isLargerThan2880px,
isLargerThan3840px,
backgroundLoaded720,
backgroundLoaded1920,
backgroundLoaded2880,
backgroundLoaded3840,
]);
useLayoutEffect(() => {
const imageLoader720 = new Image();
imageLoader720.src = `${AWS_PATH}/product-background-720x405.png`;
imageLoader720.onload = () => {
setBackgroundLoaded720(true);
};
}, []);
useLayoutEffect(() => {
const imageLoader1920 = new Image();
imageLoader1920.src = `${AWS_PATH}/product-background-1920x1080.png`;
imageLoader1920.onload = () => {
setBackgroundLoaded1920(true);
};
}, []);
useLayoutEffect(() => {
const imageLoader2880 = new Image();
imageLoader2880.src = `${AWS_PATH}/product-background-2880x1620.png`;
imageLoader2880.onload = () => {
setBackgroundLoaded2880(true);
};
}, []);
useLayoutEffect(() => {
const imageLoader3840 = new Image();
imageLoader3840.src = `${AWS_PATH}/product-background-3840x2160.png`;
imageLoader3840.onload = () => {
setBackgroundLoaded3840(true);
};
}, []);
const margin = useBreakpointValue({
base: "1%",
sm: "2%",
md: "3%",
lg: "15%",
xl: "20%",
"2xl": "25%",
});
return (
<Flex
bgPos="bottom"
bgColor="transparent"
backgroundImage={`url(${assets[`${background}`]})`}
bgSize="cover"
// boxSize="full"
minH="100vh"
direction="column"
alignItems="center"
pb={24}
>
<Stack mx={margin} my={12} maxW="1700px">
<Heading as="h2" size="md" w="100%" px={12} py={2} borderTopRadius="xl">
{`Why you'll love moonstream`}
</Heading>
<chakra.span pl={2} px={12} py={2}>
<Text mb={2}>
We strive for financial inclusion. With cryptocurrencies becoming
mainstream, now is the time for anyone with a computer and access to
the Internet to utilize this opportunity to make passive income.
Were here to make it easier.
</Text>
<Text mb={2}>
Right now our source of data is Ethereum blockchain. Our goal is to
provide a live view of the transactions taking place on every public
blockchain - from the activity of specific accounts or smart
contracts to updates about general market movements.
</Text>
<Text mb={2}>
This information comes from the blockchains themselves, from their
mempools/transaction pools, and from centralized exchanges, social
media, and the news. This forms a stream of information tailored to
your specific needs.
</Text>
<Text mb={2}>
Were giving you a macro view of the crypto market with direct
access from Moonstream dashboards to execute transactions. You can
also set up programs which execute (on- or off-chain) when your
stream meets certain conditions.
</Text>
<Text mb={2}>
Moonstream is accessible through dashboard, API and webhooks.
</Text>
<Text mb={2}>
Moonstreams financial inclusion goes beyond providing access to
data. All of our work is open source as we do not believe that
proprietary technologies are financially inclusive.
</Text>
<Text mb={2}>
You can read{" "}
<Link
textColor="primary.500"
isExternal
href="https://github.com/bugout-dev/moonstream"
>
our code on GitHub.
</Link>{" "}
and keep track of our progress using{" "}
<Link
textColor="primary.500"
isExternal
href="https://github.com/bugout-dev/moonstream/milestones"
>
the Moonstream milestones
</Link>
.
</Text>
</chakra.span>
</Stack>
<Stack mx={margin} mb={12} maxW="1700px" bgTra>
<Heading as="h2" size="md" w="100%" px={12} py={2} borderTopRadius="xl">
Product
</Heading>
<chakra.span pl={2} px={12} py={2}>
<Text mb={2}>
Moonstream is a product which helps anyone participate in
decentralized finance. From the most sophisticated flash
arbitrageurs to people looking for yield from currency that would
otherwise lie dormant in their exchange accounts.
</Text>
<Text mb={2}>
We aim to go far beyond raw transaction information, enriching our
view with context from centralized exchanges, the news, social
media, and smart contract analysis.
</Text>
<Text mb={2}>
Moonstream users can subscribe to events from any blockchain - from
the activity of specific accounts or smart contracts to updates
about general market movements. This information comes from the
blockchains themselves, from their <b>mempools/transaction</b>{" "}
pools, and from centralized exchanges, social media, and the news.
This forms a stream of information tailored to their specific needs.
</Text>
<Text mb={2}>
They can use this information to execute transactions directly from
the Moonstream frontend or they can set up programs which execute
(on- or off-chain) when their stream meets certain conditions.
</Text>
<Text mb={2}>
Moonstream will be accessible to software through our API and
webhooks.
</Text>
<chakra.span>
<Text>Moonstream customers are:</Text>
<UnorderedList w="75%" pl={4}>
<ListItem>
<b>Development teams deploying decentralized applications -</b>
They use Moonstream to analyze how users are calling their
dapps, and set up alerts for suspicious activity.{" "}
</ListItem>
<ListItem>
<b>Algorithmic funds - </b> They use Moonstream to execute
transactions directly on-chain under prespecified conditions.
</ListItem>
<ListItem>
<b>Crypto traders -</b> They use Moonstream to evaluate trading
strategies based on data from centralized exchanges, the
blockchain, and the transaction pool.
</ListItem>
</UnorderedList>
</chakra.span>
<Text my={2}>
Moonstreams financial inclusion goes beyond providing access to
data. We also help validators and stakers on proof of stake chains
earn rewards in excess of the validation rewards. We pay validators
to send mempool/transaction pool data back to Moonstream, and they
divide these payments between themselves and their stakers. This
helps validators attract more stake on proof of stake blockchains
like Algorand, Solana, and post-merge Ethereum. It also ensures that
Moonstream users have access to the freshest and most geographically
diverse transaction pool data on the market.
</Text>
<Text mb={2}>
All of our work is open source as we do not believe that proprietary
technologies are financially inclusive.{" "}
<Link
textColor="primary.500"
isExternal
href="https://github.com/bugout-dev/moonstream"
>
You can read our code on GitHub.
</Link>
</Text>
</chakra.span>
</Stack>
</Flex>
);
};
export default Product;

Wyświetl plik

@ -16,7 +16,7 @@ import Icon from "../../src/components/CustomIcon";
import useSignUp from "../../src/core/hooks/useSignUp";
import useUser from "../../src/core/hooks/useSignUp";
import useRouter from "../../src/core/hooks/useSignUp";
import { DEFAULT_METATAGS } from "../../src/components/constants";
import { DEFAULT_METATAGS } from "../../src/core/constants";
export async function getStaticProps() {
return {

Wyświetl plik

@ -0,0 +1,285 @@
import React, { useEffect, useState, useLayoutEffect, useContext } from "react";
import {
Heading,
Text,
Flex,
Link,
Stack,
chakra,
useMediaQuery,
UnorderedList,
ListItem,
Box,
SimpleGrid,
} from "@chakra-ui/react";
import { DEFAULT_METATAGS } from "../../src/core/constants";
import UIContext from "../../src/core/providers/UIProvider/context";
const AWS_PATH =
"https://s3.amazonaws.com/static.simiotics.com/moonstream/assets";
const assets = {
background720: `${AWS_PATH}/blog-background-720x405.png`,
background1920: `${AWS_PATH}/blog-background-720x405.png`,
background2880: `${AWS_PATH}/blog-background-720x405.png`,
background3840: `${AWS_PATH}/blog-background-720x405.png`,
team: `${AWS_PATH}/Team-page-illustration.png`,
};
const Product = () => {
const ui = useContext(UIContext);
const [background, setBackground] = useState("background720");
const [backgroundLoaded720, setBackgroundLoaded720] = useState(false);
const [backgroundLoaded1920, setBackgroundLoaded1920] = useState(false);
const [backgroundLoaded2880, setBackgroundLoaded2880] = useState(false);
const [backgroundLoaded3840, setBackgroundLoaded3840] = useState(false);
const [
isLargerThan720px,
isLargerThan1920px,
isLargerThan2880px,
isLargerThan3840px,
] = useMediaQuery([
"(min-width: 720px)",
"(min-width: 1920px)",
"(min-width: 2880px)",
"(min-width: 3840px)",
]);
useEffect(() => {
assets["background720"] = `${AWS_PATH}/blog-background-720x405.png`;
assets["background1920"] = `${AWS_PATH}/blog-background-1920x1080.png`;
assets["background2880"] = `${AWS_PATH}/blog-background-2880x1620.png`;
assets["background3840"] = `${AWS_PATH}/blog-background-3840x2160.png`;
}, []);
useLayoutEffect(() => {
if (backgroundLoaded3840) {
setBackground("background3840");
} else if (backgroundLoaded2880) {
setBackground("background2880");
} else if (backgroundLoaded1920) {
setBackground("background1920");
} else {
setBackground("background720");
}
}, [
isLargerThan720px,
isLargerThan1920px,
isLargerThan2880px,
isLargerThan3840px,
backgroundLoaded720,
backgroundLoaded1920,
backgroundLoaded2880,
backgroundLoaded3840,
]);
useLayoutEffect(() => {
const imageLoader720 = new Image();
imageLoader720.src = `${AWS_PATH}/blog-background-720x405.png`;
imageLoader720.onload = () => {
setBackgroundLoaded720(true);
};
}, []);
useLayoutEffect(() => {
const imageLoader1920 = new Image();
imageLoader1920.src = `${AWS_PATH}/blog-background-1920x1080.png`;
imageLoader1920.onload = () => {
setBackgroundLoaded1920(true);
};
}, []);
useLayoutEffect(() => {
const imageLoader2880 = new Image();
imageLoader2880.src = `${AWS_PATH}/blog-background-2880x1620.png`;
imageLoader2880.onload = () => {
setBackgroundLoaded2880(true);
};
}, []);
useLayoutEffect(() => {
const imageLoader3840 = new Image();
imageLoader3840.src = `${AWS_PATH}/blog-background-3840x2160.png`;
imageLoader3840.onload = () => {
setBackgroundLoaded3840(true);
};
}, []);
const margin = ui.isMobileView ? "3%" : "22%";
return (
<Flex
bgPos="bottom"
bgColor="transparent"
backgroundImage={`url(${assets[`${background}`]})`}
bgSize="cover"
minH="100vh"
direction="column"
alignItems="center"
w="100%"
>
<Stack mx={margin} mt={6} maxW="1700px" w="100%">
<SimpleGrid
px={12}
alignItems="start"
columns={{ base: 1, md: 2 }}
// mb={24}
spacingY={{ base: 10, md: 32 }}
spacingX={{ base: 10, md: 24 }}
>
<Box>
<Heading as="h2" size="md" w="100%" py={2} borderTopRadius="xl">
Meet The Moonstream Team
</Heading>
<chakra.span pl={2} py={2}>
<Text mb={2}>
We are a distributed team of nerds with very strong expertise in
math, software engineering, machine learning, and cryptography.
Members of our team worked at Google, at OpenAI and other great
companies.
</Text>
<Text mb={2}>
We believe that the crypto world opens opportunities for
financial inclusion. Meaning that people from all walks of life
and financial situations can have a new source of income. We are
passionate about developing technology that helps people become
active participants in this field and take advantage of this
opportunity. Were striving to debunk harmful stereotypes and
make the crypto field more inclusive.
</Text>
</chakra.span>
</Box>
<Box
w="full"
h="full"
py={48}
backgroundImage={`url(${assets[`team`]})`}
backgroundSize="cover"
bgPos="bottom"
bgColor="transparent"
></Box>
</SimpleGrid>
</Stack>
<Stack mx={margin} mb={6} mt={0} maxW="1700px" w="100%">
<Heading
as="h2"
size="md"
w="100%"
px={12}
pb={2}
pt={0}
borderTopRadius="xl"
>
Values that we share within our team:
</Heading>
<chakra.span pl={2} px={12} py={2}>
<UnorderedList w="75%" pl={4}>
<ListItem>
<b>Be bold</b>
</ListItem>
<ListItem>
<b>Be curious</b>
</ListItem>
<ListItem>
<b>Dont be an ass</b>
</ListItem>
<ListItem>
<b>And always be kind to each other</b>
</ListItem>
</UnorderedList>
<Text my={2}>
We are always looking to hire new talents, regardless of their
backgrounds. If you are interested in working with us, send us a
message at{" "}
<Link
textColor="secondary.900"
href="mailto: careers@moonstream.to"
>
careers@moonstream.to
</Link>
</Text>
</chakra.span>
</Stack>
<Stack mx={margin} mb={12} maxW="1700px" w="100%">
<Heading as="h2" size="md" w="100%" px={12} py={2} borderTopRadius="xl">
Our engineering team
</Heading>
<chakra.span pl={2} px={12} py={2}>
<UnorderedList w="75%" pl={4} spacing={2}>
<ListItem>
<b>zomglings{". "}</b> Founder. Number theorist. Loves playing
chess while programming. Fan of GO, backgammon, and video games.
</ListItem>
<ListItem>
<b>kompotkot{". "}</b>Keeper of Secrets. Likes information
security since childhood, loves mountains and goes hiking from
time to time. Had a close call with a wild bear in a forest once.
</ListItem>
<ListItem>
<b>wizarikus{". "}</b>Wizard. Loves mountains, bicycling, and
hiking. A practicing Python wizard. Also likes to cook and play
the guitar in between data witchcraft.
</ListItem>
<ListItem>
<b>peersky{". "}</b>
{`Spectral hopper. Perceives the world as a
spectrum interacting with and within the observer's mind. Loves
to shift in time domain to spend some of it doing fire
performances, surfing, and connecting with nature.`}
</ListItem>
<ListItem>
<b>yhtyyar{". "}</b>
{`Wunderkind. Interested in Math, NLP. Loves
programming language parsing and Algorithms & Data structures.
Implementing his own dialect of LISP programming language for
scientific calculations.`}
</ListItem>
</UnorderedList>
</chakra.span>
</Stack>
<Stack mx={margin} mb={12} maxW="1700px" w="100%">
<Heading as="h2" size="md" w="100%" px={12} py={2} borderTopRadius="xl">
Our marketing and growth team
</Heading>
<chakra.span pl={2} px={12} py={2}>
<UnorderedList w="75%" pl={4}>
<ListItem>
<b>Pahita{". "}</b> Dreamer. An alien who pretends to be a human.
So far so good. Loves ecstatic dance, being alone in nature and
dreaming.
</ListItem>
<ListItem>
<b>In_technicolor{". "}</b>Mediator. Loves stand-up comedy and
crying at nights. Volunteered at a horse farm once. Portrait
artist, puts the pain in painting.
</ListItem>
<ListItem>
<b>Nanaland{". "}</b>Progress and Enthusiasm. Traveled to the
North Korean border at the age of 19. Half German. Counseling
psychologist who switched to tech marketing and sales.
</ListItem>
</UnorderedList>
</chakra.span>
</Stack>
</Flex>
);
};
export async function getStaticProps() {
const assetPreload = Object.keys(assets).map((key) => {
return {
rel: "preload",
href: assets[key],
as: "image",
};
});
const preconnects = [{ rel: "preconnect", href: "https://s3.amazonaws.com" }];
const preloads = assetPreload.concat(preconnects);
return {
props: { metaTags: { ...DEFAULT_METATAGS }, preloads },
};
}
export default Product;

Wyświetl plik

@ -18,6 +18,11 @@ import {
Flex,
IconButton,
Tooltip,
Accordion,
AccordionItem,
AccordionButton,
AccordionPanel,
AccordionIcon,
} from "@chakra-ui/react";
import StepProgress from "../src/components/StepProgress";
import { ArrowLeftIcon, ArrowRightIcon } from "@chakra-ui/icons";
@ -31,7 +36,6 @@ import router from "next/router";
import { FaFilter } from "react-icons/fa";
const Welcome = () => {
console.count("render welcome!");
const { subscriptionsCache } = useSubscriptions();
const ui = useContext(UIContext);
const { mixpanel, isLoaded, MIXPANEL_PROPS } = useContext(AnalyticsContext);
@ -99,22 +103,19 @@ const Welcome = () => {
py={4}
>
<Heading as="h4" size="md">
Greetings traveller!
Greetings traveler!
</Heading>
<Text fontWeight="semibold" pl={2}>
{" "}
We are very excited to see you onboard!
</Text>
<Text fontWeight="semibold" pl={2}>
Moonstream is a product which helps anyone participate in
decentralized finance. From the most sophisticated flash
arbitrageurs to people looking for yield from currency that
would otherwise lie dormant in their exchange accounts.
decentralized finance.
</Text>
<Text fontWeight="semibold" pl={2}>
Moonstream is ment to give you critical insights needed to
succeed in your crypto quest!
Moonstream is meant to give you critical insights youll need
to succeed in your crypto quest!
</Text>
</Stack>
<Stack
@ -125,38 +126,54 @@ const Welcome = () => {
boxShadow="xl"
py={4}
>
<Heading as="h4" size="md">
How does Moonstream work?
</Heading>
<chakra.span fontWeight="semibold" pl={2}>
<Text fontWeight="bold" display="inline">
We run nodes
</Text>{" "}
- Now get most precise and accurate data you can just query
our database. You {`don't`} need to maintain your node, and
still have data that miners have access to!
</chakra.span>
<chakra.span fontWeight="semibold" pl={2}>
<Text fontWeight="bold" display="inline">
We crawl data
</Text>{" "}
We analyze millions of transactions, data, smart contract code
to link all them together
</chakra.span>
<Accordion allowToggle>
<AccordionItem borderWidth={0}>
<h2>
<AccordionButton borderWidth={0}>
<Heading as="h4" size="md">
How does Moonstream work?
</Heading>
<AccordionIcon />
</AccordionButton>
</h2>
<AccordionPanel pb={4} borderWidth={0}>
<Stack direction="column">
<chakra.span fontWeight="semibold" pl={2}>
<Text fontWeight="bold" display="inline">
We run nodes
</Text>{" "}
- Get precise and accurate data by querying our
database. Youre getting the same data miners have
access to and you dont have to maintain your own
node.
</chakra.span>
<chakra.span fontWeight="semibold" pl={2}>
<Text fontWeight="bold" display="inline">
We crawl data
</Text>{" "}
- We analyze millions of transactions, data, and smart
contract code to link them together.
</chakra.span>
<chakra.span fontWeight="semibold" pl={2}>
<Text fontWeight="bold" display="inline">
We provide data
</Text>{" "}
We allow you to fetch data trough the website or trough API
</chakra.span>
<chakra.span fontWeight="semibold" pl={2}>
<Text fontWeight="bold" display="inline">
We provide data
</Text>
- You can fetch data through our front end or through
API.
</chakra.span>
<chakra.span fontWeight="semibold" pl={2}>
<Text fontWeight="bold" display="inline">
We analyze data
</Text>{" "}
We find most interesting stuff and show it to you!
</chakra.span>
<chakra.span fontWeight="semibold" pl={2}>
<Text fontWeight="bold" display="inline">
We analyze data
</Text>
- We find the most interesting information and
highlight it
</chakra.span>
</Stack>
</AccordionPanel>
</AccordionItem>
</Accordion>
</Stack>
<Stack
px={12}
@ -166,55 +183,71 @@ const Welcome = () => {
boxShadow="xl"
py={4}
>
<Heading as="h4" size="md">
UI 101?
</Heading>
<Text fontWeight="semibold" pl={2}>
On the left side corner there is sidebar that you can use to
navigate across the website. There are following views you can
navigate to:
</Text>
<chakra.span fontWeight="semibold" pl={2}>
<Text fontWeight="bold" display="inline">
Subscriptions
</Text>{" "}
- Use this screen to set up addresses you would like to
monitor to.{" "}
<i>
NB: Without setting up subscriptions moonstream will have
quite empty feel!{" "}
</i>{" "}
No worries, we will help you to set up your subscriptions in
the next steps!
</chakra.span>
<chakra.span fontWeight="semibold" pl={2}>
<Text fontWeight="bold" display="inline">
Stream
</Text>{" "}
This view is somewhat similar to a bank statement where you
can define time range and see what happened in that time over
your subscriptions. In next steps we will show how you can
apply filters to it!
</chakra.span>
<Accordion allowToggle>
<AccordionItem borderWidth={0}>
<h2>
<AccordionButton borderWidth={0}>
<Heading as="h4" size="md">
UI navigation basics
</Heading>
<AccordionIcon />
</AccordionButton>
</h2>
<AccordionPanel pb={4} borderWidth={0}>
<Stack dir="column">
<Text fontWeight="semibold" pl={2}>
Use the sidebar on the left for navigation:
</Text>
<chakra.span fontWeight="semibold" pl={2}>
<Text fontWeight="bold" display="inline">
Subscriptions
</Text>
Set up addresses you would like to monitor.{" "}
<i>
NB: Without any subscriptions, Moonstream will feel
quite empty!
</i>{" "}
No worries, we will help you set up your
subscriptions.
<i>
NB: Without setting up subscriptions moonstream will
have quite empty feel!{" "}
</i>{" "}
No worries, we will help you to set up your
subscriptions in the next steps!
</chakra.span>
<chakra.span fontWeight="semibold" pl={2}>
<Text fontWeight="bold" display="inline">
Stream
</Text>{" "}
This view is similar to a bank statement. You can
define a date range and see what happened with your
subscriptions during that time. You can also apply
filters to it.
</chakra.span>
<chakra.span fontWeight="semibold" pl={2}>
<Text fontWeight="bold" display="inline">
Stream Entry
</Text>{" "}
You can see detailed view of stream cards with very specific
and essential data, like methods called in smart contracts
etc!!
</chakra.span>
<chakra.span fontWeight="semibold" pl={2}>
<Text fontWeight="bold" display="inline">
Stream Entry
</Text>{" "}
- See a detailed view of stream cards with specific
and essential data, like methods called in smart
contracts etc
</chakra.span>
<chakra.span fontWeight="semibold" pl={2}>
<Text fontWeight="bold" display="inline">
Analytics
</Text>{" "}
This section is under construction yet. Soon you will be able
to create your dashboard with data of your interest. We will
really appretiate if you visit that section, and fill up form
describing what analytical tools you would love to see there!
</chakra.span>
<chakra.span fontWeight="semibold" pl={2}>
<Text fontWeight="bold" display="inline">
Analytics
</Text>{" "}
- This section is under construction. Soon you will be
able to create dashboards there. Right now you can
fill out a form to tell us what analytical tools youd
want to see. Wed really appreciate that :)
</chakra.span>
</Stack>
</AccordionPanel>
</AccordionItem>
</Accordion>
</Stack>
<Stack
@ -226,25 +259,32 @@ const Welcome = () => {
py={4}
>
<Heading as="h4" size="md">
Tell us more about your needs?
Tell us more about your needs
</Heading>
<Text fontWeight="semibold" pl={2}>
In order to fetch best possible experience, we would like to
know some details about you
In order to create the best possible experience, we would love
to find out some more about you.
</Text>
<Text fontWeight="semibold" pl={2}>
Please tell us what profile describes you best?{" "}
Please tell us what profile describes you best.{" "}
<i>
This is purely analytical data, you can change it anytime
later
later.
</i>
</Text>
<RadioGroup
position="relative"
onChange={setProfile}
value={profile}
fontWeight="bold"
// fontWeight="bold"
colorScheme="secondary"
// py={0}
// my={0}
>
<Stack direction="row" justifyContent="space-evenly">
<Stack
direction={["column", "row", null]}
justifyContent="space-evenly"
>
<Radio value="trader">I am trading crypto currency</Radio>
<Radio value="fund">I represent investment fund</Radio>
<Radio value="developer">I am developer</Radio>
@ -270,24 +310,26 @@ const Welcome = () => {
Subscriptions
</Heading>
<chakra.span fontWeight="semibold" pl={2}>
Subscriptions is essential tool of Moonstream. We gather data
for you based on addresses you have subscribed for.
Subscriptions are an essential tool of Moonstream. We gather
data for you based on addresses you have subscribed to.
<br />
Subscribe to any addres which you are interested in and they
will become part of your stream!
Subscribe to any address you are interested in and it will
become part of your stream.
<br />
Name of subscription (you can change it later).
<UnorderedList>
<ListItem>
Color - you can define color to easily identify this
Color - you can set colors to easily identify a
subscription in your stream
</ListItem>
<ListItem>Address - thing you subscribe to</ListItem>
<ListItem>Address - the address you subscribe to</ListItem>
<ListItem>
Label - Its good idea to use human readible name that
represents address
Label - we recommend using a human-readable name that
represents the subscription
</ListItem>
<ListItem>
Source - In Alpha we support only Ethereum blockchain,
more sources are coming soon!
Source - In Alpha were only supporting Ethereum
blockchain, but more sources are coming soon!
</ListItem>
</UnorderedList>
</chakra.span>
@ -342,35 +384,32 @@ const Welcome = () => {
<chakra.span fontWeight="semibold" pl={2}>
We are almost done!
<br />
{`Stream is where you can read data you've subscribed for. Here
you have different cards for different subscription types.`}
{`Stream is where you can read data you've subscribed to. There are different cards for different subscription types.`}
<br />
If card has some extra details - there will be orange button
on right hand side inviting you to see more!
If the card has some extra details, there will be an orange
button on the right hand side inviting you to see more!
<br />
Below is typical card for ethereum blockchain event. Useful
information right on the card:
Below is a typical card for an Ethereum blockchain event.
Useful information right on the card:
<UnorderedList py={2}>
<ListItem>Hash - unique ID of the event </ListItem>
<ListItem>Hash - Unique ID of the event</ListItem>
<ListItem>
From - sender address. If it is one of your subscription
addresses - will appear in color and with label{" "}
From - Sender address. If it is one of your subscription
addresses, it will appear in color with a label
</ListItem>
<ListItem>
To - receiver address. If it is one of your subscription
addresses - will appear in color and with label{" "}
To - Receiver address. If it is one of your subscription
addresses, it will appear in color with a label
</ListItem>
<ListItem>
Nonce - Counter how many transactions address has sent. It
also determines sequence of transaction!{" "}
Nonce - Counter how many transaction addresses have been
sent. It also determines the sequence of transactions!
</ListItem>
<ListItem>
Gas Price - this is how much ether is being paid per gas
Gas Price - This is how much ether is being paid per gas
unit
</ListItem>
<ListItem>
Gas - Ammount of gas this event consumes
</ListItem>
<ListItem>Gas - Amount of gas this event consumes</ListItem>
</UnorderedList>
</chakra.span>
</Stack>
@ -402,6 +441,7 @@ const Welcome = () => {
<StreamEntry
mt={20}
entry={{
event_type: "ethereum_blockchain",
from_address: "this is address from",
to_address: "this is to address",
hash: "this is hash",
@ -422,9 +462,10 @@ const Welcome = () => {
Applying filters
</Heading>
<chakra.span fontWeight="semibold" pl={2}>
You can apply various filters by clicking filter menu button
You can apply various filters by clicking the filter menu
button.
<br />
{`Right now you can use it to select address from and to, we are adding more complex queries soon, stay tuna! `}
{`Right now you can use it to select addresses from and to, and we are adding more complex queries soon — stay tuned!`}
<br />
</chakra.span>
</Stack>
@ -444,20 +485,30 @@ const Welcome = () => {
scrollRef?.current?.scrollIntoView();
}}
>
Previous
Go back
</Button>
<Spacer />
<Button
colorScheme="secondary"
variant="solid"
rightIcon={<ArrowRightIcon />}
// hidden={!(ui.onboardingStep < ui.onboardingSteps.length - 1)}
// disabled={!(ui.onboardingStep < ui.onboardingSteps.length - 1)}
colorScheme={
ui.onboardingStep < ui.onboardingSteps.length - 1
? `secondary`
: `suggested`
}
variant={
ui.onboardingStep < ui.onboardingSteps.length - 1
? `solid`
: `outline`
}
rightIcon={
ui.onboardingStep < ui.onboardingSteps.length - 1 && (
<ArrowRightIcon />
)
}
onClick={() => handleNextClick()}
>
{ui.onboardingStep < ui.onboardingSteps.length - 1
? `Next`
: `Finish `}
: `Finish and move to stream`}
</Button>
</ButtonGroup>
</Stack>

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 3.1 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 18 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 14 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 60 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 3.0 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 15 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 674 B

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 1.2 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 1006 B

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 2.4 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 15 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 15 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 5.3 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 2.7 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 2.5 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 2.5 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 11 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 2.6 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 4.2 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 1.9 KiB

Wyświetl plik

@ -0,0 +1,92 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="1934.000000pt" height="1934.000000pt" viewBox="0 0 1934.000000 1934.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.14, written by Peter Selinger 2001-2017
</metadata>
<g transform="translate(0.000000,1934.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M10270 15789 c-79 -13 -177 -65 -236 -124 -148 -148 -172 -389 -54
-560 17 -25 32 -45 34 -45 1 0 -10 26 -26 58 -143 289 69 632 392 632 101 0
195 -34 284 -102 l41 -32 -44 47 c-95 100 -249 149 -391 126z"/>
<path d="M8760 15571 c-474 -103 -798 -554 -742 -1032 21 -179 104 -376 209
-494 l35 -40 -27 45 c-49 83 -94 186 -117 271 -19 71 -23 108 -23 239 0 131 4
167 23 233 82 284 260 498 514 617 140 65 230 85 398 85 168 0 258 -20 397
-85 100 -47 160 -87 237 -159 65 -61 65 -53 2 23 -100 120 -278 231 -451 282
-123 36 -329 43 -455 15z"/>
<path d="M13208 13945 c-271 -52 -494 -246 -584 -510 -35 -104 -44 -289 -20
-405 19 -89 70 -200 132 -287 51 -72 68 -84 29 -20 -36 57 -69 130 -91 202
-15 47 -19 91 -18 205 0 132 2 152 28 225 112 324 388 525 721 525 181 0 334
-54 480 -170 l80 -64 -43 52 c-84 100 -249 201 -387 237 -88 23 -235 27 -327
10z"/>
<path d="M9188 13533 c-172 -228 -356 -609 -448 -925 -76 -265 -105 -471 -104
-758 0 -242 13 -366 59 -555 14 -55 25 -104 25 -108 0 -4 -20 -16 -44 -27 -24
-10 -47 -23 -50 -29 -14 -22 -45 -10 -87 37 -367 400 -963 692 -1579 773 l-95
12 -72 68 c-525 496 -1322 617 -1983 303 -443 -211 -775 -587 -929 -1050 -66
-198 -91 -356 -91 -571 0 -421 142 -813 412 -1140 33 -40 62 -73 64 -73 2 0
-21 37 -50 82 -145 224 -246 503 -277 769 -18 154 -6 403 25 555 134 638 585
1143 1202 1344 433 141 897 111 1312 -86 93 -44 312 -175 312 -187 0 -2 -87
-2 -192 0 -106 3 -220 1 -253 -4 -58 -8 -60 -9 -60 -38 0 -28 3 -30 45 -37 25
-3 86 -7 135 -8 87 -1 231 -15 405 -40 76 -12 88 -16 118 -47 32 -35 46 -36
15 -1 -9 10 -14 20 -12 23 3 2 53 -7 112 -20 366 -83 702 -224 995 -418 133
-88 351 -258 406 -315 30 -33 30 -30 4 -140 -16 -67 0 -148 48 -251 54 -117
51 -131 -57 -247 -50 -54 -113 -132 -141 -174 -66 -99 -240 -455 -318 -649
-298 -744 -585 -1951 -690 -2906 -37 -330 -38 -551 -3 -641 3 -10 -2 -14 -18
-14 -46 0 -187 -57 -257 -104 -151 -100 -268 -269 -306 -443 -20 -90 -20 -238
-1 -321 82 -347 427 -586 783 -542 259 33 481 201 577 439 15 35 25 64 23 65
-2 2 -131 8 -288 14 -315 13 -520 30 -805 67 -271 36 -245 26 -245 94 0 77 32
199 75 285 56 114 165 228 282 297 45 27 210 86 217 78 1 -2 15 -25 30 -52 35
-62 113 -123 184 -143 71 -21 147 -15 275 21 l98 28 36 -34 37 -34 -28 38
c-19 27 -23 38 -14 42 7 2 60 18 118 36 247 75 499 183 678 291 50 31 92 55
92 53 0 -2 -14 -35 -30 -74 -143 -335 -127 -761 40 -1091 143 -283 418 -522
728 -634 263 -94 601 -94 864 0 429 154 748 521 837 962 23 112 37 283 27 335
l-6 35 -142 -54 c-566 -215 -1199 -378 -1794 -463 -217 -31 -496 -63 -502 -57
-2 2 -13 48 -24 102 -27 129 -29 350 -5 476 74 377 294 690 622 885 221 132
507 197 760 173 296 -27 563 -146 773 -343 93 -88 63 -40 -47 76 -173 181
-394 306 -645 365 -95 22 -135 26 -279 26 -108 1 -159 4 -145 10 85 33 250
120 286 151 78 68 106 154 77 240 -10 28 -110 248 -223 490 -238 512 -262 565
-258 565 2 0 39 -46 82 -102 278 -363 452 -522 574 -522 80 0 120 45 141 160
20 107 -4 233 -94 499 -36 105 -64 191 -63 192 3 4 305 -459 337 -516 62 -112
242 -372 271 -395 52 -39 115 -51 179 -33 30 8 62 18 73 22 13 6 8 -6 -18 -42
-46 -65 -92 -166 -111 -246 -21 -90 -19 -247 5 -341 23 -90 85 -214 136 -271
30 -34 32 -35 14 -8 -87 133 -131 323 -109 478 37 268 219 495 469 581 247 86
515 33 709 -141 45 -41 51 -44 33 -18 -32 46 -131 133 -195 171 -156 94 -369
124 -548 77 l-53 -14 104 97 c56 53 109 101 117 106 9 4 48 3 92 -3 73 -12 81
-11 216 23 503 126 862 318 1294 694 256 223 308 289 318 403 10 103 -57 265
-145 352 -160 158 -953 527 -1717 800 -1001 357 -1826 541 -2349 524 -120 -4
-198 -12 -260 -26 -50 -12 -97 -21 -105 -21 -9 0 -31 26 -49 58 -66 116 -164
204 -266 238 -24 8 -51 23 -60 33 -25 28 -56 295 -63 541 -6 246 8 407 57 650
70 340 212 709 398 1032 65 113 70 126 50 146 -22 22 -44 12 -80 -35z m352
-6697 c0 -2 -7 -7 -16 -10 -8 -3 -12 -2 -9 4 6 10 25 14 25 6z"/>
<path d="M5715 13101 c-80 -37 -125 -111 -125 -203 0 -51 27 -129 48 -142 5
-3 1 11 -10 32 -30 58 -22 158 18 214 66 94 188 121 289 65 l50 -28 -33 29
c-60 53 -163 67 -237 33z"/>
<path d="M13173 12315 c-89 -45 -137 -147 -114 -242 7 -26 21 -59 32 -73 l20
-25 -17 35 c-25 50 -23 134 4 187 63 120 225 158 323 75 34 -28 39 -22 7 9
-65 62 -170 76 -255 34z"/>
<path d="M15311 10964 c-219 -59 -360 -277 -323 -497 13 -76 48 -156 87 -202
l26 -30 -25 45 c-98 179 -64 395 83 533 161 151 394 160 576 22 l50 -37 -49
50 c-109 112 -273 157 -425 116z"/>
<path d="M3231 9884 c-81 -22 -147 -62 -206 -126 -128 -138 -157 -322 -77
-492 16 -34 39 -72 50 -86 18 -20 16 -14 -8 35 -51 106 -63 203 -35 308 21 80
46 125 105 191 154 167 417 184 599 39 l46 -36 -49 50 c-108 113 -272 158
-425 117z"/>
<path d="M16691 9202 c-59 -163 -310 -687 -451 -937 -1044 -1858 -2717 -3254
-4716 -3935 -703 -239 -1377 -376 -2144 -437 -413 -32 -1034 -23 -1485 23
-1353 136 -2630 586 -3799 1339 l-59 38 24 -34 c13 -19 76 -100 141 -181 536
-672 1202 -1249 1943 -1683 1951 -1143 4347 -1273 6415 -348 1197 536 2235
1413 2967 2508 644 963 1031 2041 1147 3195 15 144 37 482 32 487 -1 1 -8 -14
-15 -35z"/>
<path d="M4149 8987 c-78 -41 -132 -153 -113 -233 7 -29 41 -104 48 -104 1 0
-6 26 -17 58 -25 76 -12 140 40 202 73 85 169 102 269 49 46 -24 54 -26 40
-10 -56 62 -186 81 -267 38z"/>
<path d="M11702 6219 c-115 -57 -159 -229 -82 -321 l20 -23 -16 33 c-40 82
-22 181 44 245 39 38 105 67 152 67 36 0 108 -26 135 -48 l20 -17 -20 24 c-50
60 -173 79 -253 40z"/>
<path d="M11920 6001 c-52 -26 -138 -66 -190 -90 -90 -40 -94 -44 -75 -58 92
-71 208 -70 292 2 47 40 76 104 71 157 l-3 35 -95 -46z"/>
</g>
</svg>

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 5.8 KiB

Wyświetl plik

@ -1,106 +0,0 @@
import { useUser, useRouter } from "../core/hooks";
import React, { useEffect, Fragment, useState } from "react";
import { Heading, Center, Spinner, Link, Button } from "@chakra-ui/react";
import RouterLink from "next/link";
const ACCOUNT_SCREEN_WIDGETS = {
tokens: "tokens",
security: "security",
teams: "teams",
};
const AccountNavbar = () => {
const router = useRouter();
const [CurrentWidget, setCurrentWidget] = useState();
const { user, isInit } = useUser();
useEffect(() => {
if (isInit) {
if (user) {
if (router.pathname === "/account") {
router.replace("/account/teams");
}
} else {
router.replace("/register");
}
}
}, [router, CurrentWidget, user, isInit]);
useEffect(() => {
setCurrentWidget(router.nextRouter.query.page);
}, [setCurrentWidget, router.nextRouter.query.page]);
if (!user && !isInit)
return (
<Center>
<Spinner
hidden={false}
my={32}
size="lg"
color="primary.500"
thickness="4px"
speed="1.5s"
/>
</Center>
);
return (
<Fragment>
<Center>
<Heading as="h1" fontSize={["md", "lg"]} py={4} color="black.100">
My Account
</Heading>
</Center>
<Link
as={RouterLink}
href={`/account/${ACCOUNT_SCREEN_WIDGETS.teams}`}
passHref
>
<Button
isActive={CurrentWidget === ACCOUNT_SCREEN_WIDGETS.teams}
// ref={TeamsButtonRef}
// href={`/account/${ACCOUNT_SCREEN_WIDGETS.teams}`}
variant="accountMenu"
colorScheme="secondary"
as={Link}
>
Teams
</Button>
</Link>
<Link
as={RouterLink}
href={`/account/${encodeURIComponent(ACCOUNT_SCREEN_WIDGETS.tokens)}`}
passHref
>
<Button
as={Link}
isActive={CurrentWidget === ACCOUNT_SCREEN_WIDGETS.tokens}
// ref={TokensButtonRef}
colorScheme="secondary"
variant="accountMenu"
>
Tokens
</Button>
</Link>
<Link
as={RouterLink}
href={`/account/${ACCOUNT_SCREEN_WIDGETS.security}`}
passHref
>
<Button
isActive={CurrentWidget === ACCOUNT_SCREEN_WIDGETS.security}
as={Link}
// ref={SecurityButtonRef}
// as={RouterLink}
// href={`/account/${ACCOUNT_SCREEN_WIDGETS.security}`}
variant="accountMenu"
colorScheme="secondary"
>
Security
</Button>
</Link>
</Fragment>
);
};
export default AccountNavbar;

Wyświetl plik

@ -28,6 +28,7 @@ import useRouter from "../core/hooks/useRouter";
import UIContext from "../core/providers/UIProvider/context";
import AccountIconButton from "./AccountIconButton";
import RouteButton from "./RouteButton";
import { USER_NAV_PATHES, ALL_NAV_PATHES } from "../core/constants";
const AppNavbar = () => {
const ui = useContext(UIContext);
@ -97,13 +98,37 @@ const AppNavbar = () => {
<Flex width="100%" px={2}>
<Spacer />
<Flex placeSelf="flex-end">
<ButtonGroup spacing={4}>
{/* <RouteButton variant="link" href="/docs">
Docs
</RouteButton> */}
<RouteButton variant="link" href="/welcome">
Learn how to
</RouteButton>
<ButtonGroup spacing={4} colorScheme="secondary">
{ALL_NAV_PATHES.map((item, idx) => (
<RouteButton
key={`${idx}-${item.title}-landing-all-links`}
variant="link"
href={item.path}
color="white"
isActive={!!(router.nextRouter.pathname === item.path)}
>
{item.title}
</RouteButton>
))}
{USER_NAV_PATHES.map((item, idx) => {
console.log(
"item.path:",
item.path,
"pathname:",
router.nextRouter.pathname
);
return (
<RouteButton
key={`${idx}-${item.title}-navlink`}
variant="link"
href={item.path}
color="white"
isActive={!!(router.nextRouter.pathname === item.path)}
>
{item.title}
</RouteButton>
);
})}
</ButtonGroup>
<SupportPopover />
<AccountIconButton

Wyświetl plik

@ -0,0 +1,29 @@
import React from "react";
import {
VStack,
Code,
} from "@chakra-ui/react";
import { Table, Thead, Tbody, Tr, Th, Td } from "@chakra-ui/react";
const ContractSource = ({ source_info }) => {
return (
<VStack spacing={3}>
<Table>
<Thead>
<Tr>
<Th>Contract Name</Th>
<Th>Compiler version</Th>
</Tr>
</Thead>
<Tbody>
<Tr key={source_info.name}>
<Td>{source_info.name} </Td>
<Td>{source_info.compiler_version}</Td>
</Tr>
</Tbody>
</Table>
<Code colorScheme="blackAlpha" w="110%" >{source_info.source_code}</Code>
</VStack>)
}
export default ContractSource;

Wyświetl plik

@ -1,6 +1,7 @@
import React from "react";
import { Flex, Text, Link } from "@chakra-ui/react";
import { Flex, Text, Link, Heading } from "@chakra-ui/react";
import CustomIcon from "../components/CustomIcon";
import RouterLink from "next/link";
const ICONS = [
{
@ -22,6 +23,11 @@ const SITEMAP_FLEX_PROPS = {
mr: 12,
};
const LINKS_SIZES = {
fontWeight: "300",
fontSize: "lg",
};
const Footer = () => (
<Flex
bg="brand.200"
@ -42,31 +48,28 @@ const Footer = () => (
maxW="40rem"
>
<Flex {...SITEMAP_FLEX_PROPS}>
{/* <Heading pb={8} size="md">
<Heading pb={8} size="md">
About
</Heading> */}
{/* <RouterLink passHref href="/team">
</Heading>{" "}
<RouterLink passHref href="/team">
<Link {...LINKS_SIZES}>Team</Link>
</RouterLink> */}
{/* <RouterLink passHref href="/events">
<Link {...LINKS_SIZES}>Events</Link>
</RouterLink>
<RouterLink passHref href="http://blog.bugout.dev">
<Link {...LINKS_SIZES}>Blog</Link>
</RouterLink> */}
<RouterLink passHref href="/product">
<Link {...LINKS_SIZES}>Product</Link>
</RouterLink>
</Flex>
<Flex {...SITEMAP_FLEX_PROPS}>
{/* <Heading pb={8} size="md">
Legal
<Heading pb={8} size="md">
News
</Heading>
<RouterLink href="/tos" passHref>
<Link {...LINKS_SIZES}>Terms of service</Link>
</RouterLink> */}
<RouterLink passHref href="http://blog.moonstream.to">
<Link {...LINKS_SIZES}>Blog</Link>
</RouterLink>
{/* <RouterLink passHref href="/privacy-policy">
<Link {...LINKS_SIZES}>Privacy policy</Link>
</RouterLink> */}
</Flex>
{/* <Flex {...SITEMAP_FLEX_PROPS}>
<Heading pb={8} size="md">
Product
@ -94,7 +97,7 @@ const Footer = () => (
fontSize="xl"
fontWeight="500"
>
Stay in touch{` `}
All the crypto data you care about{` `}
<span role="img" aria-label="heart">
💙
</span>

Wyświetl plik

@ -14,6 +14,8 @@ import useModals from "../core/hooks/useModals";
import UIContext from "../core/providers/UIProvider/context";
import ChakraAccountIconButton from "./AccountIconButton";
import RouteButton from "./RouteButton";
import { ALL_NAV_PATHES } from "../core/constants";
import router from "next/router";
const LandingNavbar = () => {
const ui = useContext(UIContext);
@ -53,16 +55,17 @@ const LandingNavbar = () => {
spacing={4}
pr={16}
>
{ui.isLoggedIn && (
<ButtonGroup spacing={4}>
{/* <RouteButton variant="link" href="/docs">
Docs
</RouteButton> */}
<RouteButton variant="link" href="/welcome">
Learn how to
</RouteButton>
</ButtonGroup>
)}
{ALL_NAV_PATHES.map((item, idx) => (
<RouteButton
key={`${idx}-${item.title}-landing-all-links`}
variant="link"
href={item.path}
color="white"
isActive={!!(router.pathname === item.path)}
>
{item.title}
</RouteButton>
))}
{ui.isLoggedIn && (
<RouterLink href="/stream" passHref>

Wyświetl plik

@ -15,7 +15,7 @@ const Modal = ({ children, onClose }) => (
sx={{ filter: "grayscale: 50%" }}
fill="primary.800"
src={
"https://s3.amazonaws.com/static.simiotics.com/moonstream/assets/White+logo.svg"
"https://s3.amazonaws.com/static.simiotics.com/moonstream/assets/logo-black.svg"
}
/>
<Flex cursor="pointer" onClick={onClose} css={styles.close}>

Wyświetl plik

@ -129,7 +129,6 @@ const NewSubscription = ({ isFreeOption, onClose }) => {
</Text>{" "}
<IconButton
size="md"
// colorScheme="primary"
color={"white.100"}
_hover={{ bgColor: { color } }}
bgColor={color}
@ -148,10 +147,7 @@ const NewSubscription = ({ isFreeOption, onClose }) => {
></Input>
</Stack>
<GithubPicker
// color={this.state.background}
onChangeComplete={handleChangeColorComplete}
/>
<GithubPicker onChangeComplete={handleChangeColorComplete} />
<FormErrorMessage color="unsafe.400" pl="1">
{errors.color && errors.color.message}

Wyświetl plik

@ -73,7 +73,7 @@ const _NewSubscription = ({ isFreeOption, onClose, setIsLoading }) => {
my={2}
type="text"
autoComplete="off"
placeholder="Meaningful name of your subscription"
placeholder="Name of subscription (you can change it later)"
name="label"
ref={register({ required: "label is required!" })}
></Input>

Wyświetl plik

@ -10,12 +10,12 @@ import {
Icon,
useColorModeValue,
Button,
Center,
useBreakpointValue,
} from "@chakra-ui/react";
// import Xarrow, { useXarrow } from "react-xarrows";
import React, { useContext } from "react";
import UIContext from "../core/providers/UIProvider/context";
import { FaGithubSquare } from "react-icons/fa";
import RouteButton from "../components/RouteButton";
const Feature = ({ text, icon, iconBg, bullets }) => {
return (
@ -67,16 +67,20 @@ const SplitWithImage = ({
mirror,
elementName,
cta,
socialButton,
}) => {
const buttonSize = useBreakpointValue({
base: "md",
sm: "md",
md: "md",
lg: "lg",
xl: "xl",
"2xl": "xl",
var buttonSize = useBreakpointValue({
base: { single: "sm", double: "xs" },
sm: { single: "md", double: "sm" },
md: { single: "md", double: "sm" },
lg: { single: "lg", double: "lg" },
xl: { single: "lg", double: "lg" },
"2xl": { single: "lg", double: "lg" },
});
//idk why but sometimes buttonSize gets undefined
if (!buttonSize) buttonSize = "lg";
const ui = useContext(UIContext);
const [isVisible, setVisible] = React.useState(true);
@ -109,20 +113,25 @@ const SplitWithImage = ({
</Flex>
)}
<Stack spacing={4} justifyContent="center">
<Text
id={`MoonBadge ${elementName}`}
// id={`MoonBadge${elementName}`}
textTransform={"uppercase"}
color={useColorModeValue(`${colorScheme}.50`, `${colorScheme}.900`)}
fontWeight={600}
fontSize={"sm"}
bg={useColorModeValue(`${colorScheme}.900`, `${colorScheme}.50`)}
p={2}
alignSelf={mirror && !ui.isMobileView ? "flex-end" : "flex-start"}
rounded={"md"}
>
{badge}
</Text>
<Stack direction="row">
<Text
id={`MoonBadge ${elementName}`}
// id={`MoonBadge${elementName}`}
textTransform={"uppercase"}
color={useColorModeValue(
`${colorScheme}.50`,
`${colorScheme}.900`
)}
fontWeight={600}
fontSize={"sm"}
bg={useColorModeValue(`${colorScheme}.900`, `${colorScheme}.50`)}
p={2}
alignSelf={mirror && !ui.isMobileView ? "flex-end" : "flex-start"}
rounded={"md"}
>
{badge}
</Text>
</Stack>
<Heading>{title}</Heading>
<Text color={`primary.500`} fontSize={"lg"}>
{body}
@ -148,20 +157,40 @@ const SplitWithImage = ({
/>
);
})}
<Container>
<Center>
<Button
colorScheme={colorScheme}
variant="outline"
<Flex
w="100%"
flexWrap="nowrap"
display={["column", "column", null, "row"]}
>
<Button
colorScheme={colorScheme}
w={["100%", "100%", "fit-content", null]}
maxW={["250px", null, "fit-content"]}
variant="outline"
mt={[0, 0, null, 16]}
size={socialButton ? buttonSize.double : buttonSize.single}
onClick={cta.onClick}
>
{cta.label}
</Button>
{socialButton && (
<RouteButton
isExternal
w={["100%", "100%", "fit-content", null]}
maxW={["250px", null, "fit-content"]}
href={socialButton.url}
mt={[0, 0, null, 16]}
fontSize={["xs", "sm", "lg", null, "lg"]}
size={buttonSize}
onClick={cta.onClick}
size={socialButton ? buttonSize.double : buttonSize.single}
variant="outline"
colorScheme="primary"
leftIcon={<FaGithubSquare />}
>
{cta.label}
</Button>
</Center>
</Container>
git clone moonstream
</RouteButton>
)}
</Flex>
</Stack>
</Stack>
{(!mirror || ui.isMobileView) && (
@ -171,7 +200,6 @@ const SplitWithImage = ({
alt={"feature image"}
src={imgURL}
objectFit={"contain"}
// boxSize={ui.isMobileView ? "lg" : null}
/>
</Flex>
)}

Wyświetl plik

@ -1,52 +1,11 @@
import React, { useContext, useEffect, useState } from "react";
import {
Flex,
Text,
IconButton,
Stack,
Tooltip,
useClipboard,
Heading,
Image,
useMediaQuery,
Spacer,
Spinner,
chakra,
} from "@chakra-ui/react";
import moment from "moment";
import React, { useContext } from "react";
import { Flex, IconButton, Stack, Tooltip, chakra } from "@chakra-ui/react";
import { ArrowRightIcon } from "@chakra-ui/icons";
import UIContext from "../core/providers/UIProvider/context";
import { useToast } from "../core/hooks";
import { useSubscriptions } from "../core/hooks";
import EthereumMempoolCard from "./stream-cards/EthereumMempool";
const StreamEntry = ({ entry, showOnboardingTooltips, className }) => {
const { subscriptionsCache } = useSubscriptions();
const StreamEntry_ = ({ entry, showOnboardingTooltips, className }) => {
const ui = useContext(UIContext);
const [copyString, setCopyString] = useState(false);
const { onCopy, hasCopied } = useClipboard(copyString, 1);
const toast = useToast();
useEffect(() => {
if (hasCopied && copyString) {
toast("Copied to clipboard", "success");
setCopyString(false);
} else if (copyString) {
onCopy();
}
}, [copyString, onCopy, hasCopied, toast]);
const [showFullView] = useMediaQuery(["(min-width: 420px)"]);
if (subscriptionsCache.isLoading) return <Spinner />;
const from_color =
subscriptionsCache.data.subscriptions.find((obj) => {
return obj.address === entry.from_address;
})?.color ?? "gray.500";
const to_color =
subscriptionsCache.data.subscriptions.find((obj) => {
return obj.address === entry.to_address;
})?.color ?? "gray.500";
return (
<Flex
@ -75,273 +34,17 @@ const StreamEntry = ({ entry, showOnboardingTooltips, className }) => {
h="100%"
spacing={0}
>
{true && (
<Stack
my={0}
direction="column"
flexBasis="10px"
flexGrow={1}
borderWidth="2px"
borderLeftRadius="md"
borderColor="gray.600"
spacing={0}
h="auto"
// h="fit-content"
// minH="fit-content"
overflowX="hidden"
overflowY="visible"
>
<Tooltip
hasArrow
isOpen={showOnboardingTooltips}
// shouldWrapChildren
label="Top of card describes type of event. Ethereum blockchain in this case. It as unique hash shown here"
variant="onboarding"
placement="top"
>
<Stack
className="title"
direction="row"
w="100%"
h="1.6rem"
minH="1.6rem"
textAlign="center"
spacing={0}
alignItems="center"
bgColor="gray.300"
>
<Image
boxSize="16px"
src={
"https://upload.wikimedia.org/wikipedia/commons/0/05/Ethereum_logo_2014.svg"
}
/>
<Heading px={1} size="xs">
Hash
</Heading>
<Spacer />
<Text
isTruncated
onClick={() => setCopyString(entry.hash)}
pr={12}
>
{entry.hash}
</Text>
</Stack>
</Tooltip>
<Stack
className="CardAddressesRow"
direction={showFullView ? "row" : "column"}
w="100%"
h={showFullView ? "1.6rem" : "3.2rem"}
minH="1.6rem"
textAlign="center"
spacing={0}
alignItems="center"
>
<Stack
overflow="hidden"
textOverflow="ellipsis"
whiteSpace="nowrap"
direction="row"
fontSize="sm"
fontWeight="600"
minw="min-content"
w={showFullView ? "calc(50%)" : "calc(100%)"}
h="100%"
borderColor="gray.1200"
borderRightWidth={showFullView ? "1px" : "0px"}
placeContent="center"
spacing={0}
>
<Tooltip
hasArrow
isOpen={showOnboardingTooltips && !ui.isMobileView}
label="From and to addresses, clicking names will copy address to clipboard!"
variant="onboarding"
placement={ui.isMobileView ? "bottom" : "left"}
maxW="150px"
>
<Text
bgColor="gray.600"
h="100%"
fontSize="sm"
py="2px"
px={2}
w={showFullView ? null : "120px"}
>
From:
</Text>
</Tooltip>
<Tooltip label={entry.from_address} aria-label="From:">
<Text
mx={0}
py="2px"
fontSize="sm"
bgColor={from_color}
isTruncated
w="calc(100%)"
h="100%"
onClick={() => setCopyString(entry.from_address)}
>
{entry.from_label ?? entry.from_address}
</Text>
</Tooltip>
</Stack>
<Stack
overflow="hidden"
textOverflow="ellipsis"
whiteSpace="nowrap"
direction="row"
fontSize="sm"
fontWeight="600"
minw="min-content"
w={showFullView ? "calc(50%)" : "calc(100%)"}
h="100%"
spacing={0}
>
<Text
bgColor="gray.600"
h="100%"
py={1}
px={2}
w={showFullView ? null : "120px"}
>
To:
</Text>
<Tooltip label={entry.to_address} aria-label="From:">
<Text
bgColor={to_color}
isTruncated
w="calc(100%)"
h="100%"
onClick={() => setCopyString(entry.to_address)}
>
{entry.to_label ?? entry.to_address}
</Text>
</Tooltip>
</Stack>
</Stack>
<Flex flexWrap="wrap" w="100%">
<Flex minH="2rem" minW="fit-content" flexGrow={1}>
<Text
h="100%"
fontSize="sm"
py="2px"
px={2}
whiteSpace="nowrap"
w={showFullView ? null : "120px"}
textAlign="justify"
>
Gas Price:
</Text>
<Tooltip label={entry.gasPrice} aria-label="Gas Price:">
<Text
mx={0}
py="2px"
fontSize="sm"
w="calc(100%)"
h="100%"
onClick={() => setCopyString(entry.gasPrice)}
>
{entry.gasPrice}
</Text>
</Tooltip>
</Flex>
<Flex h="2rem" minW="fit-content" flexGrow={1}>
<Text
w={showFullView ? null : "120px"}
h="100%"
fontSize="sm"
py="2px"
px={2}
textAlign="justify"
>
Gas:
</Text>
<Tooltip label={entry.gas} aria-label="Gas:">
<Text
mx={0}
py="2px"
fontSize="sm"
w="calc(100%)"
h="100%"
onClick={() => setCopyString(entry.gas)}
>
{entry.gas}
</Text>
</Tooltip>
</Flex>
<Flex h="2rem" minW="fit-content" flexGrow={1}>
<Text
w={showFullView ? null : "120px"}
h="100%"
fontSize="sm"
py="2px"
px={2}
textAlign="justify"
>
Value:
</Text>
<Tooltip label={entry.value} aria-label="Value:">
<Text
mx={0}
py="2px"
fontSize="sm"
w="calc(100%)"
h="100%"
onClick={() => setCopyString(entry.value)}
>
{entry.value}
</Text>
</Tooltip>
</Flex>
<Flex h="2rem" minW="fit-content" flexGrow={1}>
<Text
w={showFullView ? null : "120px"}
h="100%"
fontSize="sm"
py="2px"
px={2}
textAlign="justify"
>
Nonce:
</Text>
<Tooltip label={entry.value} aria-label="Value:">
<Text
mx={0}
py="2px"
fontSize="sm"
w="calc(100%)"
h="100%"
onClick={() => setCopyString(entry.value)}
>
{entry.nonce}
</Text>
</Tooltip>
</Flex>
{entry.timestamp && (
<Flex h="auto" minW="fit-content">
<Text
px={1}
mx={0}
py="2px"
fontSize="sm"
w="calc(100%)"
h="100%"
borderColor="gray.700"
>
{moment(entry.timestamp * 1000).format(
"DD MMM, YYYY, HH:mm:ss"
)}{" "}
</Text>
</Flex>
)}
</Flex>
</Stack>
{entry.subscription_type_id === "0" && (
<EthereumMempoolCard entry={entry} />
)}
{/* ToDo: Add another types of cards in here
{entryType === "<name>" && (
<Card entry={entry} />
)}
*/}
<Flex>
<Tooltip
hasArrow
@ -355,7 +58,6 @@ const StreamEntry = ({ entry, showOnboardingTooltips, className }) => {
m={0}
onClick={() => ui.setCurrentTransaction(entry)}
h="full"
// minH="24px"
borderLeftRadius={0}
variant="solid"
px={0}
@ -370,6 +72,6 @@ const StreamEntry = ({ entry, showOnboardingTooltips, className }) => {
);
};
const StreamChakraEntry = chakra(StreamEntry);
const StreamEntry = chakra(StreamEntry_);
export default StreamChakraEntry;
export default StreamEntry;

Wyświetl plik

@ -9,6 +9,7 @@ import {
Box,
VStack,
} from "@chakra-ui/react";
import ContractSource from './ContractSource'
import { Table, Thead, Tbody, Tr, Th, Td } from "@chakra-ui/react";
const toEth = (wei) => {
return wei / Math.pow(10, 18);
@ -94,10 +95,13 @@ const TxInfo = (props) => {
)}
</Tbody>
</Table>
{transaction.tx.input && transaction.tx.input !== "0x" && (
<TxABI byteCode={transaction.tx.input} abi={transaction.abi} />
)}
</Box>
{transaction.smart_contract_info && <ContractSource source_info={transaction.smart_contract_info} />}
{
transaction.tx.input && transaction.tx.input !== "0x" && (
<TxABI byteCode={transaction.tx.input} abi={transaction.abi} />
)
}
</Box >
);
};
export default TxInfo;

Wyświetl plik

@ -1,25 +0,0 @@
export const PERMISSION_LEVELS = { none: 0, member: 1, admin: 10, owner: 100 };
export const PRESIGNED_URL_TYPE = {
SESSIONS: "session",
CLIENTS: "client",
REPORTS: "stats",
ERRORS: "errors",
};
export const DEFAULT_METATAGS = {
title: "Bugout: Measure the success of your dev tool",
description:
"Get usage metrics and crash reports. Improve your users' experience",
keywords:
"bugout, bugout-dev, bugout.dev, usage-metrics, analytics, dev-tool ,knowledge, docs, journal, entry, find-anything",
url: "https://bugout.dev",
image: "https://s3.amazonaws.com/static.simiotics.com/landing/aviator-2.svg",
};
export const PRESERVE_QUERY_ACROSS_JOURNALS = false;
export const PRICING_OPTIONS = { DEV: 1, NIGHTLY: 2, STABLE: 3 };
const constants = { PERMISSION_LEVELS, PRESIGNED_URL_TYPE, DEFAULT_METATAGS };
export default constants;

Wyświetl plik

@ -0,0 +1,313 @@
import React, { useContext, useEffect, useState } from "react";
import {
Flex,
Text,
Stack,
Tooltip,
useClipboard,
Heading,
Image,
useMediaQuery,
Spacer,
Spinner,
chakra,
} from "@chakra-ui/react";
import moment from "moment";
import UIContext from "../../core/providers/UIProvider/context";
import { useToast } from "../../core/hooks";
import { useSubscriptions } from "../../core/hooks";
const EthereumMempoolCard_ = ({ entry, showOnboardingTooltips, className }) => {
const { subscriptionsCache } = useSubscriptions();
const ui = useContext(UIContext);
const [copyString, setCopyString] = useState(false);
const { onCopy, hasCopied } = useClipboard(copyString, 1);
const toast = useToast();
useEffect(() => {
if (hasCopied && copyString) {
toast("Copied to clipboard", "success");
setCopyString(false);
} else if (copyString) {
onCopy();
}
}, [copyString, onCopy, hasCopied, toast]);
const [showFullView] = useMediaQuery(["(min-width: 420px)"]);
if (subscriptionsCache.isLoading) return <Spinner />;
const from_color =
subscriptionsCache.data.subscriptions.find((obj) => {
return obj.address === entry.from_address;
})?.color ?? "gray.500";
const to_color =
subscriptionsCache.data.subscriptions.find((obj) => {
return obj.address === entry.to_address;
})?.color ?? "gray.500";
return (
<Stack className={className}>
<Tooltip
hasArrow
isOpen={showOnboardingTooltips}
label="Top of card describes type of event. Ethereum blockchain in this case. It as unique hash shown here"
variant="onboarding"
placement="top"
>
<Stack
className="title"
direction="row"
w="100%"
h="1.6rem"
minH="1.6rem"
textAlign="center"
spacing={0}
alignItems="center"
bgColor="gray.300"
>
<Image
boxSize="16px"
src={
"https://upload.wikimedia.org/wikipedia/commons/0/05/Ethereum_logo_2014.svg"
}
/>
<Heading px={1} size="xs">
Hash
</Heading>
<Spacer />
<Text isTruncated onClick={() => setCopyString(entry.hash)} pr={12}>
{entry.hash}
</Text>
</Stack>
</Tooltip>
<Stack
className="CardAddressesRow"
direction={showFullView ? "row" : "column"}
w="100%"
h={showFullView ? "1.6rem" : "3.2rem"}
minH="1.6rem"
textAlign="center"
spacing={0}
alignItems="center"
>
<Stack
overflow="hidden"
textOverflow="ellipsis"
whiteSpace="nowrap"
direction="row"
fontSize="sm"
fontWeight="600"
minw="min-content"
w={showFullView ? "calc(50%)" : "calc(100%)"}
h="100%"
borderColor="gray.1200"
borderRightWidth={showFullView ? "1px" : "0px"}
placeContent="center"
spacing={0}
>
<Tooltip
hasArrow
isOpen={showOnboardingTooltips && !ui.isMobileView}
label="From and to addresses, clicking names will copy address to clipboard!"
variant="onboarding"
placement={ui.isMobileView ? "bottom" : "left"}
maxW="150px"
>
<Text
bgColor="gray.600"
h="100%"
fontSize="sm"
py="2px"
px={2}
w={showFullView ? null : "120px"}
>
From:
</Text>
</Tooltip>
<Tooltip label={entry.from_address} aria-label="From:">
<Text
mx={0}
py="2px"
fontSize="sm"
bgColor={from_color}
isTruncated
w="calc(100%)"
h="100%"
onClick={() => setCopyString(entry.from_address)}
>
{entry.from_label ?? entry.from_address}
</Text>
</Tooltip>
</Stack>
<Stack
overflow="hidden"
textOverflow="ellipsis"
whiteSpace="nowrap"
direction="row"
fontSize="sm"
fontWeight="600"
minw="min-content"
w={showFullView ? "calc(50%)" : "calc(100%)"}
h="100%"
spacing={0}
>
<Text
bgColor="gray.600"
h="100%"
py={1}
px={2}
w={showFullView ? null : "120px"}
>
To:
</Text>
<Tooltip label={entry.to_address} aria-label="From:">
<Text
bgColor={to_color}
isTruncated
w="calc(100%)"
h="100%"
onClick={() => setCopyString(entry.to_address)}
>
{entry.to_label ?? entry.to_address}
</Text>
</Tooltip>
</Stack>
</Stack>
<Flex flexWrap="wrap" w="100%">
<Flex minH="2rem" minW="fit-content" flexGrow={1}>
<Text
h="100%"
fontSize="sm"
py="2px"
px={2}
whiteSpace="nowrap"
w={showFullView ? null : "120px"}
textAlign="justify"
>
Gas Price:
</Text>
<Tooltip label={entry.gasPrice} aria-label="Gas Price:">
<Text
mx={0}
py="2px"
fontSize="sm"
w="calc(100%)"
h="100%"
onClick={() => setCopyString(entry.gasPrice)}
>
{entry.gasPrice}
</Text>
</Tooltip>
</Flex>
<Flex h="2rem" minW="fit-content" flexGrow={1}>
<Text
w={showFullView ? null : "120px"}
h="100%"
fontSize="sm"
py="2px"
px={2}
textAlign="justify"
>
Gas:
</Text>
<Tooltip label={entry.gas} aria-label="Gas:">
<Text
mx={0}
py="2px"
fontSize="sm"
w="calc(100%)"
h="100%"
onClick={() => setCopyString(entry.gas)}
>
{entry.gas}
</Text>
</Tooltip>
</Flex>
<Flex h="2rem" minW="fit-content" flexGrow={1}>
<Text
w={showFullView ? null : "120px"}
h="100%"
fontSize="sm"
py="2px"
px={2}
textAlign="justify"
>
Value:
</Text>
<Tooltip label={entry.value} aria-label="Value:">
<Text
mx={0}
py="2px"
fontSize="sm"
w="calc(100%)"
h="100%"
onClick={() => setCopyString(entry.value)}
>
{entry.value}
</Text>
</Tooltip>
</Flex>
<Flex h="2rem" minW="fit-content" flexGrow={1}>
<Text
w={showFullView ? null : "120px"}
h="100%"
fontSize="sm"
py="2px"
px={2}
textAlign="justify"
>
Nonce:
</Text>
<Tooltip label={entry.value} aria-label="Value:">
<Text
mx={0}
py="2px"
fontSize="sm"
w="calc(100%)"
h="100%"
onClick={() => setCopyString(entry.value)}
>
{entry.nonce}
</Text>
</Tooltip>
</Flex>
{entry.timestamp && (
<Flex h="auto" minW="fit-content">
<Text
px={1}
mx={0}
py="2px"
fontSize="sm"
w="calc(100%)"
h="100%"
borderColor="gray.700"
>
{moment(entry.timestamp * 1000).format("DD MMM, YYYY, HH:mm:ss")}{" "}
</Text>
</Flex>
)}
</Flex>
</Stack>
);
};
const EthereumMempoolCard = chakra(EthereumMempoolCard_, {
baseStyle: {
my: 0,
direction: "column",
flexBasis: "10px",
flexGrow: 1,
borderWidth: "2px",
borderLeftRadius: "md",
borderColor: "gray.600",
spacing: 0,
h: "auto",
overflowX: "hidden",
overflowY: "visible",
},
});
export default EthereumMempoolCard;

Wyświetl plik

@ -4,3 +4,31 @@ export const BUGOUT_ENDPOINTS = {
Usage: "usage",
Web: "parasite",
};
export const DEFAULT_METATAGS = {
title: "Moonstream.to: All your crypto data in one stream",
description:
"From the Ethereum transaction pool to Elon Musks latest tweets get all the crypto data you care about in one stream.",
keywords:
"blockchain, crypto, data, trading, smart contracts, ethereum, solana, transactions, defi, finance, decentralized",
url: "https://www.moonstream.to",
image: `https://s3.amazonaws.com/static.simiotics.com/moonstream/assets/crypto+traders.png`,
};
export const ALL_NAV_PATHES = [
{
title: "Product",
path: "/product",
},
{
title: "Team",
path: "/team",
},
];
export const USER_NAV_PATHES = [
{
title: "Learn how to",
path: "/welcome",
},
];