Merge branch 'main' into go-txpool-crawler
|
@ -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/
|
||||
|
|
|
@ -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/
|
||||
|
|
|
@ -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/
|
||||
|
|
|
@ -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.
|
||||
"""
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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]])
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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 Musk’s 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`}
|
||||
|
|
|
@ -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.
|
||||
We’re 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}>
|
||||
We’re 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}>
|
||||
Moonstream’s 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}>
|
||||
Moonstream’s 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;
|
|
@ -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 {
|
||||
|
|
|
@ -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. We’re 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>Don’t 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;
|
|
@ -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 you’ll 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. You’re getting the same data miners have
|
||||
access to and you don’t 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 you’d
|
||||
want to see. We’d 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 we’re 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>
|
||||
|
|
Przed Szerokość: | Wysokość: | Rozmiar: 3.1 KiB Po Szerokość: | Wysokość: | Rozmiar: 18 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 14 KiB Po Szerokość: | Wysokość: | Rozmiar: 60 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 3.0 KiB Po Szerokość: | Wysokość: | Rozmiar: 15 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 674 B Po Szerokość: | Wysokość: | Rozmiar: 1.2 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 1006 B Po Szerokość: | Wysokość: | Rozmiar: 2.4 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 15 KiB Po Szerokość: | Wysokość: | Rozmiar: 15 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 5.3 KiB Po Szerokość: | Wysokość: | Rozmiar: 2.7 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 2.5 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 2.5 KiB Po Szerokość: | Wysokość: | Rozmiar: 11 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 2.6 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 4.2 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 1.9 KiB |
|
@ -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 |
|
@ -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;
|
|
@ -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
|
||||
|
|
|
@ -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;
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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}>
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
)}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
|
@ -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;
|
|
@ -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 Musk’s 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",
|
||||
},
|
||||
];
|
||||
|
|