Merge branch 'main' into change-navbar-logo

pull/156/head
Tim Pechersky 2021-08-24 18:06:08 +02:00
commit ed641fb67d
18 zmienionych plików z 424 dodań i 308 usunięć

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

@ -1,14 +1,11 @@
from datetime import datetime import json
import logging import logging
from typing import Dict, Any, List, Optional
import boto3 # type: ignore
from typing import Dict, Any, List, Optional, Union
from sqlalchemy.engine.base import Transaction
from moonstreamdb.models import ( from moonstreamdb.models import (
EthereumBlock, EthereumBlock,
EthereumTransaction, EthereumTransaction,
EthereumPendingTransaction,
EthereumAddress, EthereumAddress,
EthereumLabel, EthereumLabel,
) )
@ -16,12 +13,10 @@ from sqlalchemy import or_, and_, text
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from . import data from . import data
from .settings import DEFAULT_STREAM_TIMEINTERVAL, ETHERSCAN_SMARTCONTRACTS_BUCKET from .settings import DEFAULT_STREAM_TIMEINTERVAL, ETHERSCAN_SMARTCONTRACTS_BUCKET
import boto3
import json
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
ETHERSCAN_SMARTCONTRACT_LABEL_NAME = "etherscan_smartcontract"
async def get_transaction_in_blocks( async def get_transaction_in_blocks(
@ -264,7 +259,7 @@ def parse_search_query_to_sqlalchemy_filters(q: str, allowed_addresses: List[str
return constructed_filters return constructed_filters
def get_source_code( def get_contract_source_info(
db_session: Session, contract_address: str db_session: Session, contract_address: str
) -> Optional[data.EthereumSmartContractSourceInfo]: ) -> Optional[data.EthereumSmartContractSourceInfo]:
query = db_session.query(EthereumAddress.id).filter( query = db_session.query(EthereumAddress.id).filter(
@ -278,7 +273,7 @@ def get_source_code(
) )
for label in labels: for label in labels:
if label.label == "etherscan_smartcontract": if label.label == ETHERSCAN_SMARTCONTRACT_LABEL_NAME:
object_uri = label.label_data["object_uri"] object_uri = label.label_data["object_uri"]
key = object_uri.split("s3://etherscan-smart-contracts/")[1] key = object_uri.split("s3://etherscan-smart-contracts/")[1]
s3 = boto3.client("s3") s3 = boto3.client("s3")
@ -294,13 +289,13 @@ def get_source_code(
) )
return contract_source_info return contract_source_info
except: except:
logger.error(f"Failed to load smart contract {contract_address}") logger.error(f"Failed to load smart contract {object_uri}")
return None return None
def get_address_labels( def get_address_labels(
db_session: Session, start: int, limit: int, addresses: Optional[List[str]] = None db_session: Session, start: int, limit: int, addresses: Optional[str] = None
) -> List[EthereumAddress]: ) -> data.AddressListLabelsResponse:
""" """
Attach labels to addresses. Attach labels to addresses.
""" """

Wyświetl plik

@ -84,11 +84,13 @@ async def txinfo_ethereum_blockchain_handler(
if smart_contract is not None: if smart_contract is not None:
response.is_smart_contract_deployment = True response.is_smart_contract_deployment = True
else: else:
response.smart_contract_info = actions.get_source_code( source_info = actions.get_contract_source_info(
db_session, txinfo_request.tx.to_address db_session, txinfo_request.tx.to_address
) )
response.smart_contract_address = txinfo_request.tx.to_address if source_info is not None:
response.is_smart_contract_call = True response.smart_contract_info = source_info
response.smart_contract_address = txinfo_request.tx.to_address
response.is_smart_contract_call = True
return response return response
@ -97,8 +99,8 @@ async def txinfo_ethereum_blockchain_handler(
) )
async def addresses_labels_handler( async def addresses_labels_handler(
addresses: Optional[str] = Query(None), addresses: Optional[str] = Query(None),
start: Optional[int] = Query(0), start: int = Query(0),
limit: Optional[int] = Query(100), limit: int = Query(100),
db_session: Session = Depends(yield_db_session), db_session: Session = Depends(yield_db_session),
) -> data.AddressListLabelsResponse: ) -> data.AddressListLabelsResponse:
""" """
@ -110,11 +112,11 @@ async def addresses_labels_handler(
status_code=406, detail="The limit cannot exceed 100 addresses" status_code=406, detail="The limit cannot exceed 100 addresses"
) )
try: try:
addresses = actions.get_address_labels( addresses_response = actions.get_address_labels(
db_session=db_session, start=start, limit=limit, addresses=addresses db_session=db_session, start=start, limit=limit, addresses=addresses
) )
except Exception as err: except Exception as err:
logger.error(f"Unable to get info about Ethereum addresses {err}") logger.error(f"Unable to get info about Ethereum addresses {err}")
raise HTTPException(status_code=500) 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: if MOONSTREAM_DATA_JOURNAL_ID is None:
raise ValueError("MOONSTREAM_DATA_JOURNAL_ID environment variable must be set") raise ValueError("MOONSTREAM_DATA_JOURNAL_ID environment variable must be set")
MOONSTREAM_ADMIN_ACCESS_TOKEN = os.environ.get("MOONSTREAM_ADMIN_ACCESS_TOKEN") MOONSTREAM_ADMIN_ACCESS_TOKEN = os.environ.get("MOONSTREAM_ADMIN_ACCESS_TOKEN", "")
if MOONSTREAM_ADMIN_ACCESS_TOKEN is None: if MOONSTREAM_ADMIN_ACCESS_TOKEN == "":
raise ValueError("MOONSTREAM_ADMIN_ACCESS_TOKEN environment variable must be set") raise ValueError("MOONSTREAM_ADMIN_ACCESS_TOKEN environment variable must be set")
# Origin # Origin
@ -43,4 +43,6 @@ for path in MOONSTREAM_OPENAPI_LIST:
DEFAULT_STREAM_TIMEINTERVAL = 5 * 60 DEFAULT_STREAM_TIMEINTERVAL = 5 * 60
# S3 Bucket # S3 Bucket
ETHERSCAN_SMARTCONTRACTS_BUCKET = "etherscan-smart-contracts" ETHERSCAN_SMARTCONTRACTS_BUCKET = os.environ.get("AWS_S3_SMARTCONTRACT_BUCKET")
if ETHERSCAN_SMARTCONTRACTS_BUCKET is None:
raise ValueError("AWS_S3_SMARTCONTRACT_BUCKET is not set")

Wyświetl plik

@ -5,5 +5,6 @@ export MOONSTREAM_DATA_JOURNAL_ID="<bugout_journal_id_to_store_blockchain_data>"
export MOONSTREAM_DB_URI="postgresql://<username>:<password>@<db_host>:<db_port>/<db_name>" export MOONSTREAM_DB_URI="postgresql://<username>:<password>@<db_host>:<db_port>/<db_name>"
export MOONSTREAM_POOL_SIZE=0 export MOONSTREAM_POOL_SIZE=0
export MOONSTREAM_ADMIN_ACCESS_TOKEN="<Access token to application resources>" export MOONSTREAM_ADMIN_ACCESS_TOKEN="<Access token to application resources>"
export AWS_S3_SMARTCONTRACT_BUCKET=""
export BUGOUT_BROOD_URL="https://auth.bugout.dev" export BUGOUT_BROOD_URL="https://auth.bugout.dev"
export BUGOUT_SPIRE_URL="https://spire.bugout.dev" export BUGOUT_SPIRE_URL="https://spire.bugout.dev"

Wyświetl plik

@ -91,6 +91,8 @@ def ethcrawler_blocks_sync_handler(args: argparse.Namespace) -> None:
starting_block: int = args.start starting_block: int = args.start
while True: while True:
bottom_block_number, top_block_number = get_latest_blocks(args.confirmations) 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) bottom_block_number = max(bottom_block_number + 1, starting_block)
if bottom_block_number >= top_block_number: if bottom_block_number >= top_block_number:
print( print(

Wyświetl plik

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

Wyświetl plik

@ -1,21 +1,22 @@
import argparse 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 csv
import codecs import codecs
import json import json
import os import os
from sqlalchemy.orm import Session
import boto3 # type: ignore
from moonstreamdb.db import yield_db_session_ctx 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 from moonstreamdb.models import EthereumAddress, EthereumLabel
import requests import requests
from sqlalchemy.orm import Session
from sqlalchemy.sql.expression import text
from .version import MOONCRAWL_VERSION
from .settings import MOONSTREAM_ETHERSCAN_TOKEN from .settings import MOONSTREAM_ETHERSCAN_TOKEN
if MOONSTREAM_ETHERSCAN_TOKEN is None: if MOONSTREAM_ETHERSCAN_TOKEN is None:

Wyświetl plik

@ -1,13 +1,13 @@
import unittest import unittest
from . import cli from . import ethcrawler
class TestYieldBlockNumbersLists(unittest.TestCase): class TestYieldBlockNumbersLists(unittest.TestCase):
def test_yield_descending_10_6_step_4(self): def test_yield_descending_10_6_step_4(self):
partition = [ partition = [
block_numbers_list 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 "10-6", block_step=4
) )
] ]
@ -16,7 +16,7 @@ class TestYieldBlockNumbersLists(unittest.TestCase):
def test_yield_descending_10_6_step_3(self): def test_yield_descending_10_6_step_3(self):
partition = [ partition = [
block_numbers_list 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 "10-6", block_step=3
) )
] ]
@ -25,8 +25,8 @@ class TestYieldBlockNumbersLists(unittest.TestCase):
def test_yield_descending_10_6_descending_step_3(self): def test_yield_descending_10_6_descending_step_3(self):
partition = [ partition = [
block_numbers_list 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", cli.ProcessingOrder.DESCENDING, 3 "10-6", ethcrawler.ProcessingOrder.DESCENDING, 3
) )
] ]
self.assertListEqual(partition, [[10, 9, 8], [7, 6]]) 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): def test_yield_descending_10_6_descending_step_10(self):
partition = [ partition = [
block_numbers_list 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", cli.ProcessingOrder.DESCENDING, 10 "10-6", ethcrawler.ProcessingOrder.DESCENDING, 10
) )
] ]
self.assertListEqual(partition, [[10, 9, 8, 7, 6]]) 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): def test_yield_descending_6_10_step_4(self):
partition = [ partition = [
block_numbers_list 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 "6-10", block_step=4
) )
] ]
@ -52,7 +52,7 @@ class TestYieldBlockNumbersLists(unittest.TestCase):
def test_yield_descending_6_10_step_3(self): def test_yield_descending_6_10_step_3(self):
partition = [ partition = [
block_numbers_list 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 "6-10", block_step=3
) )
] ]
@ -61,8 +61,8 @@ class TestYieldBlockNumbersLists(unittest.TestCase):
def test_yield_descending_6_10_descending_step_3(self): def test_yield_descending_6_10_descending_step_3(self):
partition = [ partition = [
block_numbers_list 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", cli.ProcessingOrder.DESCENDING, 3 "6-10", ethcrawler.ProcessingOrder.DESCENDING, 3
) )
] ]
self.assertListEqual(partition, [[10, 9, 8], [7, 6]]) 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): def test_yield_descending_6_10_descending_step_10(self):
partition = [ partition = [
block_numbers_list 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", cli.ProcessingOrder.DESCENDING, 10 "6-10", ethcrawler.ProcessingOrder.DESCENDING, 10
) )
] ]
self.assertListEqual(partition, [[10, 9, 8, 7, 6]]) 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): def test_yield_ascending_10_6_ascending_step_3(self):
partition = [ partition = [
block_numbers_list 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", cli.ProcessingOrder.ASCENDING, 3 "10-6", ethcrawler.ProcessingOrder.ASCENDING, 3
) )
] ]
self.assertListEqual(partition, [[6, 7, 8], [9, 10]]) 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): def test_yield_ascending_10_6_ascending_step_10(self):
partition = [ partition = [
block_numbers_list 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", cli.ProcessingOrder.ASCENDING, 10 "10-6", ethcrawler.ProcessingOrder.ASCENDING, 10
) )
] ]
self.assertListEqual(partition, [[6, 7, 8, 9, 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): def test_yield_ascending_6_10_ascending_step_4(self):
partition = [ partition = [
block_numbers_list 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", cli.ProcessingOrder.ASCENDING, 4 "6-10", ethcrawler.ProcessingOrder.ASCENDING, 4
) )
] ]
self.assertListEqual(partition, [[6, 7, 8, 9], [10]]) 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): def test_yield_ascending_6_10_ascending_step_10(self):
partition = [ partition = [
block_numbers_list 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", cli.ProcessingOrder.ASCENDING, 10 "6-10", ethcrawler.ProcessingOrder.ASCENDING, 10
) )
] ]
self.assertListEqual(partition, [[6, 7, 8, 9, 10]]) self.assertListEqual(partition, [[6, 7, 8, 9, 10]])

Wyświetl plik

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

Wyświetl plik

@ -1,4 +1,4 @@
import React, { useEffect, useState, useLayoutEffect, useContext } from "react"; import React, { useEffect, useState, useLayoutEffect } from "react";
import { import {
Heading, Heading,
Text, Text,
@ -9,10 +9,9 @@ import {
useMediaQuery, useMediaQuery,
UnorderedList, UnorderedList,
ListItem, ListItem,
useBreakpointValue,
} from "@chakra-ui/react"; } from "@chakra-ui/react";
import { DEFAULT_METATAGS, AWS_ASSETS_PATH } from "../../src/core/constants"; import { DEFAULT_METATAGS, AWS_ASSETS_PATH } from "../../src/core/constants";
import UIContext from "../../src/core/providers/UIProvider/context";
export async function getStaticProps() { export async function getStaticProps() {
return { return {
props: { metaTags: { ...DEFAULT_METATAGS } }, props: { metaTags: { ...DEFAULT_METATAGS } },
@ -20,14 +19,13 @@ export async function getStaticProps() {
} }
const assets = { const assets = {
background720: `${AWS_ASSETS_PATH}/blog-background-720x405.png`, background720: `${AWS_ASSETS_PATH}/product-background-720x405.png`,
background1920: `${AWS_ASSETS_PATH}/blog-background-720x405.png`, background1920: `${AWS_ASSETS_PATH}/product-background-720x405.png`,
background2880: `${AWS_ASSETS_PATH}/blog-background-720x405.png`, background2880: `${AWS_ASSETS_PATH}/product-background-720x405.png`,
background3840: `${AWS_ASSETS_PATH}/blog-background-720x405.png`, background3840: `${AWS_ASSETS_PATH}/product-background-720x405.png`,
}; };
const Product = () => { const Product = () => {
const ui = useContext(UIContext);
const [background, setBackground] = useState("background720"); const [background, setBackground] = useState("background720");
const [backgroundLoaded720, setBackgroundLoaded720] = useState(false); const [backgroundLoaded720, setBackgroundLoaded720] = useState(false);
const [backgroundLoaded1920, setBackgroundLoaded1920] = useState(false); const [backgroundLoaded1920, setBackgroundLoaded1920] = useState(false);
@ -47,16 +45,18 @@ const Product = () => {
]); ]);
useEffect(() => { useEffect(() => {
assets["background720"] = `${AWS_ASSETS_PATH}/blog-background-720x405.png`; assets[
"background720"
] = `${AWS_ASSETS_PATH}/product-background-720x405.png`;
assets[ assets[
"background1920" "background1920"
] = `${AWS_ASSETS_PATH}/blog-background-1920x1080.png`; ] = `${AWS_ASSETS_PATH}/product-background-1920x1080.png`;
assets[ assets[
"background2880" "background2880"
] = `${AWS_ASSETS_PATH}/blog-background-2880x1620.png`; ] = `${AWS_ASSETS_PATH}/product-background-2880x1620.png`;
assets[ assets[
"background3840" "background3840"
] = `${AWS_ASSETS_PATH}/blog-background-3840x2160.png`; ] = `${AWS_ASSETS_PATH}/product-background-3840x2160.png`;
}, []); }, []);
useLayoutEffect(() => { useLayoutEffect(() => {
@ -82,7 +82,7 @@ const Product = () => {
useLayoutEffect(() => { useLayoutEffect(() => {
const imageLoader720 = new Image(); const imageLoader720 = new Image();
imageLoader720.src = `${AWS_ASSETS_PATH}/blog-background-720x405.png`; imageLoader720.src = `${AWS_ASSETS_PATH}/product-background-720x405.png`;
imageLoader720.onload = () => { imageLoader720.onload = () => {
setBackgroundLoaded720(true); setBackgroundLoaded720(true);
}; };
@ -90,7 +90,7 @@ const Product = () => {
useLayoutEffect(() => { useLayoutEffect(() => {
const imageLoader1920 = new Image(); const imageLoader1920 = new Image();
imageLoader1920.src = `${AWS_ASSETS_PATH}/blog-background-1920x1080.png`; imageLoader1920.src = `${AWS_ASSETS_PATH}/product-background-1920x1080.png`;
imageLoader1920.onload = () => { imageLoader1920.onload = () => {
setBackgroundLoaded1920(true); setBackgroundLoaded1920(true);
}; };
@ -98,7 +98,7 @@ const Product = () => {
useLayoutEffect(() => { useLayoutEffect(() => {
const imageLoader2880 = new Image(); const imageLoader2880 = new Image();
imageLoader2880.src = `${AWS_ASSETS_PATH}/blog-background-2880x1620.png`; imageLoader2880.src = `${AWS_ASSETS_PATH}/product-background-2880x1620.png`;
imageLoader2880.onload = () => { imageLoader2880.onload = () => {
setBackgroundLoaded2880(true); setBackgroundLoaded2880(true);
}; };
@ -106,13 +106,20 @@ const Product = () => {
useLayoutEffect(() => { useLayoutEffect(() => {
const imageLoader3840 = new Image(); const imageLoader3840 = new Image();
imageLoader3840.src = `${AWS_ASSETS_PATH}/blog-background-3840x2160.png`; imageLoader3840.src = `${AWS_ASSETS_PATH}/product-background-3840x2160.png`;
imageLoader3840.onload = () => { imageLoader3840.onload = () => {
setBackgroundLoaded3840(true); setBackgroundLoaded3840(true);
}; };
}, []); }, []);
const margin = ui.isMobileView ? "7%" : "25%"; const margin = useBreakpointValue({
base: "1%",
sm: "2%",
md: "3%",
lg: "15%",
xl: "20%",
"2xl": "25%",
});
return ( return (
<Flex <Flex
@ -124,36 +131,63 @@ const Product = () => {
minH="100vh" minH="100vh"
direction="column" direction="column"
alignItems="center" alignItems="center"
pb={24}
> >
<Stack mx={margin} my={12} maxW="1700px"> <Stack mx={margin} my={12} maxW="1700px">
<Heading as="h2" size="md" w="100%" px={12} py={2} borderTopRadius="xl"> <Heading as="h2" size="md" w="100%" px={12} py={2} borderTopRadius="xl">
Vision {`Why you'll love moonstream`}
</Heading> </Heading>
<chakra.span pl={2} px={12} py={2}> <chakra.span pl={2} px={12} py={2}>
<Text mb={2}> <Text mb={2}>
Our goal is to provide a live view of the transactions taking place We strive for financial inclusion. With cryptocurrencies becoming
on <b>every</b> public blockchain. 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>
<Text mb={2}> <Text mb={2}>
We aim to go far beyond raw transaction information, enriching our Right now our source of data is Ethereum blockchain. Our goal is to
view with context from centralized exchanges, the news, social provide a live view of the transactions taking place on every public
media, and smart contract analysis. blockchain - from the activity of specific accounts or smart
contracts to updates about general market movements.
</Text> </Text>
<Text mb={2}> <Text mb={2}>
Data is only as good as the decisions it informs. We are building This information comes from the blockchains themselves, from their
Moonstream to be much more than a database. We are building mempools/transaction pools, and from centralized exchanges, social
Moonstream to be an execution engine, where anyone can set up media, and the news. This forms a stream of information tailored to
triggers based on Moonstream events. Triggers can submit your specific needs.
transactions to any blockchain or they can call external APIs via
webhooks.
</Text> </Text>
<Text mb={2}> <Text mb={2}>
Moonstream will be accessible to humans through our dashboard and Were giving you a macro view of the crypto market with direct
notification system. 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>
<Text mb={2}> <Text mb={2}>
Moonstream will be accessible to software through our API and Moonstream is accessible through dashboard, API and webhooks.
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> </Text>
</chakra.span> </chakra.span>
</Stack> </Stack>
@ -177,9 +211,9 @@ const Product = () => {
Moonstream users can subscribe to events from any blockchain - from Moonstream users can subscribe to events from any blockchain - from
the activity of specific accounts or smart contracts to updates the activity of specific accounts or smart contracts to updates
about general market movements. This information comes from the about general market movements. This information comes from the
blockchains themselves, from their mempools/transaction pools, and blockchains themselves, from their <b>mempools/transaction</b>{" "}
from centralized exchanges, social media, and the news. This forms a pools, and from centralized exchanges, social media, and the news.
stream of information tailored to their specific needs. This forms a stream of information tailored to their specific needs.
</Text> </Text>
<Text mb={2}> <Text mb={2}>
They can use this information to execute transactions directly from They can use this information to execute transactions directly from

Wyświetl plik

@ -9,6 +9,8 @@ import {
useMediaQuery, useMediaQuery,
UnorderedList, UnorderedList,
ListItem, ListItem,
Box,
SimpleGrid,
} from "@chakra-ui/react"; } from "@chakra-ui/react";
import { DEFAULT_METATAGS, AWS_ASSETS_PATH } from "../../src/core/constants"; import { DEFAULT_METATAGS, AWS_ASSETS_PATH } from "../../src/core/constants";
import UIContext from "../../src/core/providers/UIProvider/context"; import UIContext from "../../src/core/providers/UIProvider/context";
@ -18,6 +20,7 @@ const assets = {
background1920: `${AWS_ASSETS_PATH}/blog-background-720x405.png`, background1920: `${AWS_ASSETS_PATH}/blog-background-720x405.png`,
background2880: `${AWS_ASSETS_PATH}/blog-background-720x405.png`, background2880: `${AWS_ASSETS_PATH}/blog-background-720x405.png`,
background3840: `${AWS_ASSETS_PATH}/blog-background-720x405.png`, background3840: `${AWS_ASSETS_PATH}/blog-background-720x405.png`,
team: `${AWS_ASSETS_PATH}/Team-page-illustration.png`,
}; };
const Product = () => { const Product = () => {
@ -119,36 +122,56 @@ const Product = () => {
alignItems="center" alignItems="center"
w="100%" w="100%"
> >
<Stack mx={margin} my={6} maxW="1700px"> <Stack mx={margin} maxW="1700px" w="100%">
<Heading as="h2" size="md" w="100%" px={12} py={2} borderTopRadius="xl"> <SimpleGrid
Meet The Moonstream Team px={12}
</Heading> alignItems="start"
<chakra.span pl={2} px={12} py={2}> columns={{ base: 1, md: 2 }}
<Text mb={2}> // mb={24}
We are a distributed team of nerds with very strong expertise in spacingY={{ base: 10, md: 32 }}
math, software engineering, machine learning, and cryptography. spacingX={{ base: 10, md: 24 }}
Members of our team worked at Google, at OpenAI and other great >
companies. <Box>
</Text> <Heading as="h2" size="md" w="100%" py={6} borderTopRadius="xl">
<Text mb={2}> Meet The Moonstream Team
We believe that the crypto world opens opportunities for financial </Heading>
inclusion. Meaning that people from all walks of life and financial <chakra.span pl={2} py={2}>
situations can have a new source of income. We are passionate about <Text mb={2}>
developing technology that helps people become active participants We are a distributed team of nerds with very strong expertise in
in this field and take advantage of this opportunity. Were striving math, software engineering, machine learning, and cryptography.
to debunk harmful stereotypes and make the crypto field more Members of our team worked at Google, at OpenAI and other great
inclusive. companies.
</Text> </Text>
</chakra.span> <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>
<Stack mx={margin} my={6} maxW="1700px"> <Stack mx={margin} mb={6} mt={0} maxW="1700px" w="100%">
<Heading <Heading
as="h2" as="h2"
size="md" size="md"
w="100%" w="100%"
// bgColor="gray.200"
px={12} px={12}
py={2} pb={2}
pt={0}
borderTopRadius="xl" borderTopRadius="xl"
> >
Values that we share within our team: Values that we share within our team:
@ -156,7 +179,10 @@ const Product = () => {
<chakra.span pl={2} px={12} py={2}> <chakra.span pl={2} px={12} py={2}>
<UnorderedList w="75%" pl={4}> <UnorderedList w="75%" pl={4}>
<ListItem> <ListItem>
<b> Be bold</b> <b>Be bold</b>
</ListItem>
<ListItem>
<b>Be curious</b>
</ListItem> </ListItem>
<ListItem> <ListItem>
<b>Dont be an ass</b> <b>Dont be an ass</b>
@ -178,43 +204,35 @@ const Product = () => {
</Text> </Text>
</chakra.span> </chakra.span>
</Stack> </Stack>
<Stack mx={margin} mb={12} maxW="1700px"> <Stack mx={margin} mb={12} maxW="1700px" w="100%">
<Heading <Heading as="h2" size="md" w="100%" px={12} py={2} borderTopRadius="xl">
as="h2"
size="md"
w="100%"
// bgColor="gray.200"
px={12}
py={2}
borderTopRadius="xl"
>
Our engineering team Our engineering team
</Heading> </Heading>
<chakra.span pl={2} px={12} py={2}> <chakra.span pl={2} px={12} py={2}>
<UnorderedList w="75%" pl={4} spacing={2}> <UnorderedList w="75%" pl={4} spacing={2}>
<ListItem> <ListItem>
<b>zomglings,</b> Founder. Number theorist. Loves playing chess <b>zomglings{". "}</b> Founder. Number theorist. Loves playing
while programming. Fan of GO, backgammon, and video games. chess while programming. Fan of GO, backgammon, and video games.
</ListItem> </ListItem>
<ListItem> <ListItem>
<b>kompotkot -</b>Keeper of Secrets. Likes information security <b>kompotkot{". "}</b>Keeper of Secrets. Likes information
since childhood, loves mountains and goes hiking from time to security since childhood, loves mountains and goes hiking from
time. Had a close call with a wild bear in a forest once. time to time. Had a close call with a wild bear in a forest once.
</ListItem> </ListItem>
<ListItem> <ListItem>
<b>wizarikus -</b>Wizard. Loves mountains, bicycling, and hiking. <b>wizarikus{". "}</b>Wizard. Loves mountains, bicycling, and
A practicing Python wizard. Also likes to cook and play the guitar hiking. A practicing Python wizard. Also likes to cook and play
in between data witchcraft. the guitar in between data witchcraft.
</ListItem> </ListItem>
<ListItem> <ListItem>
<b>peersky -</b> <b>peersky{". "}</b>
{`Spectral hopper. Perceives the world as a {`Spectral hopper. Perceives the world as a
spectrum interacting with and within the observer's mind. Loves spectrum interacting with and within the observer's mind. Loves
to shift in time domain to spend some of it doing fire to shift in time domain to spend some of it doing fire
performances, surfing, and connecting with nature.`} performances, surfing, and connecting with nature.`}
</ListItem> </ListItem>
<ListItem> <ListItem>
<b>yhtyyar -</b> <b>yhtyyar{". "}</b>
{`Wunderkind. Interested in Math, NLP. Loves {`Wunderkind. Interested in Math, NLP. Loves
programming language parsing and Algorithms & Data structures. programming language parsing and Algorithms & Data structures.
Implementing his own dialect of LISP programming language for Implementing his own dialect of LISP programming language for
@ -223,25 +241,25 @@ const Product = () => {
</UnorderedList> </UnorderedList>
</chakra.span> </chakra.span>
</Stack> </Stack>
<Stack mx={margin} mb={12} maxW="1700px"> <Stack mx={margin} mb={12} maxW="1700px" w="100%">
<Heading as="h2" size="md" w="100%" px={12} py={2} borderTopRadius="xl"> <Heading as="h2" size="md" w="100%" px={12} py={2} borderTopRadius="xl">
Our marketing and growth team Our marketing and growth team
</Heading> </Heading>
<chakra.span pl={2} px={12} py={2}> <chakra.span pl={2} px={12} py={2}>
<UnorderedList w="75%" pl={4}> <UnorderedList w="75%" pl={4}>
<ListItem> <ListItem>
<b>Pahita.</b> Dreamer. An alien who pretends to be a human. So <b>Pahita{". "}</b> Dreamer. An alien who pretends to be a human.
far so good. Loves ecstatic dance, being alone in nature and So far so good. Loves ecstatic dance, being alone in nature and
dreaming. dreaming.
</ListItem> </ListItem>
<ListItem> <ListItem>
<b>In_technicolor,</b>Mediator. Loves stand-up comedy and crying <b>In_technicolor{". "}</b>Mediator. Loves stand-up comedy and
at nights. Volunteered at a horse farm once. Portrait artist, puts crying at nights. Volunteered at a horse farm once. Portrait
the pain in painting. artist, puts the pain in painting.
</ListItem> </ListItem>
<ListItem> <ListItem>
<b>Nanaland.</b>Progress and Enthusiasm. Traveled to the North <b>Nanaland{". "}</b>Progress and Enthusiasm. Traveled to the
Korean border at the age of 19. Half German. Counseling North Korean border at the age of 19. Half German. Counseling
psychologist who switched to tech marketing and sales. psychologist who switched to tech marketing and sales.
</ListItem> </ListItem>
</UnorderedList> </UnorderedList>

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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