Merge branch 'main' into moonstream-api-docs-endpoint

pull/268/head
kompotkot 2021-10-11 10:59:45 +00:00
commit 969c6a76df
13 zmienionych plików z 607 dodań i 29 usunięć

Wyświetl plik

@ -21,6 +21,8 @@ from ..settings import ETHTXPOOL_HUMBUG_CLIENT_ID
logger = logging.getLogger(__name__)
logger.setLevel(logging.WARN)
allowed_tags = ["tag:erc721"]
class BugoutEventProviderError(Exception):
"""
@ -315,14 +317,17 @@ class EthereumTXPoolProvider(BugoutEventProvider):
]
subscriptions_filters = []
for address in addresses:
subscriptions_filters.extend(
[f"?#from_address:{address}", f"?#to_address:{address}"]
)
if address in allowed_tags:
subscriptions_filters.append(address)
else:
subscriptions_filters.extend(
[f"?#from_address:{address}", f"?#to_address:{address}"]
)
return subscriptions_filters
class NftProvider(BugoutEventProvider):
class PublicDataProvider(BugoutEventProvider):
def __init__(
self,
event_type: str,
@ -359,7 +364,7 @@ Shows the top 10 addresses active on the Ethereum blockchain over the last hour
4. Amount (in WEI) received
To restrict your queries to this provider, add a filter of \"type:ethereum_whalewatch\" to your query (query parameter: \"q\") on the /streams endpoint."""
whalewatch_provider = BugoutEventProvider(
whalewatch_provider = PublicDataProvider(
event_type="ethereum_whalewatch",
description=whalewatch_description,
default_time_interval_seconds=310,
@ -389,7 +394,7 @@ Currently, it summarizes the activities on the following NFT markets:
This provider is currently not accessible for subscription. The data from this provider is publicly
available at the /nft endpoint."""
nft_summary_provider = NftProvider(
nft_summary_provider = PublicDataProvider(
event_type="nft_summary",
description=nft_summary_description,
# 40 blocks per summary, 15 seconds per block + 2 seconds wiggle room.

Wyświetl plik

@ -8,11 +8,14 @@ from bugout.data import BugoutResource
from moonstreamdb.models import (
EthereumBlock,
EthereumTransaction,
EthereumAddress,
EthereumLabel,
)
from sqlalchemy import or_, and_, text
from sqlalchemy.orm import Session, Query
from sqlalchemy.sql.functions import user
from .. import data
from ..stream_boundaries import validate_stream_boundary
from ..stream_queries import StreamQuery
@ -23,6 +26,7 @@ logger.setLevel(logging.WARN)
event_type = "ethereum_blockchain"
allowed_tags = ["tag:erc721"]
description = f"""Event provider for transactions from the Ethereum blockchain.
@ -79,6 +83,7 @@ class Filters:
from_addresses: List[str] = field(default_factory=list)
to_addresses: List[str] = field(default_factory=list)
labels: List[str] = field(default_factory=list)
def default_filters(subscriptions: List[BugoutResource]) -> Filters:
@ -91,8 +96,11 @@ def default_filters(subscriptions: List[BugoutResource]) -> Filters:
Optional[str], subscription.resource_data.get("address")
)
if subscription_address is not None:
filters.from_addresses.append(subscription_address)
filters.to_addresses.append(subscription_address)
if subscription_address in allowed_tags:
filters.labels.append(subscription_address.split(":")[1])
else:
filters.from_addresses.append(subscription_address)
filters.to_addresses.append(subscription_address)
else:
logger.warn(
f"Could not find subscription address for subscription with resource id: {subscription.id}"
@ -157,14 +165,20 @@ def parse_filters(
parsed_filters.from_addresses.append(address)
parsed_filters.to_addresses.append(address)
if not (parsed_filters.from_addresses or parsed_filters.to_addresses):
if not (
parsed_filters.from_addresses
or parsed_filters.to_addresses
or parsed_filters.labels
):
return None
return parsed_filters
def query_ethereum_transactions(
db_session: Session, stream_boundary: data.StreamBoundary, parsed_filters: Filters
db_session: Session,
stream_boundary: data.StreamBoundary,
parsed_filters: Filters,
) -> Query:
"""
Builds a database query for Ethereum transactions that occurred within the window of time that
@ -198,15 +212,41 @@ def query_ethereum_transactions(
query = query.filter(EthereumBlock.timestamp <= stream_boundary.end_time)
# We want to take a big disjunction (OR) over ALL the filters, be they on "from" address or "to" address
address_clauses = [
EthereumTransaction.from_address == address
for address in parsed_filters.from_addresses
] + [
EthereumTransaction.to_address == address
for address in parsed_filters.to_addresses
]
if address_clauses:
query = query.filter(or_(*address_clauses))
address_clauses = []
address_clauses.extend(
[
EthereumTransaction.from_address == address
for address in parsed_filters.from_addresses
]
+ [
EthereumTransaction.to_address == address
for address in parsed_filters.to_addresses
]
)
labels_clause = []
if parsed_filters.labels:
label_clause = (
db_session.query(EthereumAddress)
.join(EthereumLabel, EthereumAddress.id == EthereumLabel.address_id)
.filter(
or_(
*[
EthereumLabel.label.contains(label)
for label in list(set(parsed_filters.labels))
]
)
)
.exists()
)
labels_clause.append(label_clause)
subscriptions_clause = address_clauses + labels_clause
if subscriptions_clause:
query = query.filter(or_(*subscriptions_clause))
return query
@ -353,8 +393,7 @@ def next_event(
query_ethereum_transactions(db_session, next_stream_boundary, parsed_filters)
.order_by(text("timestamp asc"))
.limit(1)
.one_or_none()
)
).one_or_none()
if maybe_ethereum_transaction is None:
return None
@ -394,9 +433,7 @@ def previous_event(
)
.order_by(text("timestamp desc"))
.limit(1)
.one_or_none()
)
).one_or_none()
if maybe_ethereum_transaction is None:
return None
return ethereum_transaction_event(maybe_ethereum_transaction)

Wyświetl plik

@ -0,0 +1,93 @@
"""
Moonstream's /whales endpoints.
These endpoints provide public access to whale watch summaries. No authentication required.
"""
from datetime import datetime
import logging
from typing import Optional
from bugout.data import BugoutResource
from fastapi import Depends, FastAPI, Query
from moonstreamdb import db
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy.orm import Session
from .. import data
from ..providers.bugout import whalewatch_provider
from ..settings import (
bugout_client,
DOCS_TARGET_PATH,
MOONSTREAM_ADMIN_ACCESS_TOKEN,
MOONSTREAM_DATA_JOURNAL_ID,
ORIGINS,
)
from ..stream_queries import StreamQuery
from ..version import MOONSTREAM_VERSION
logger = logging.getLogger(__name__)
tags_metadata = [
{"name": "whales", "description": "Whales summaries"},
]
app = FastAPI(
title=f"Moonstream /whales API",
description="User, token and password handlers.",
version=MOONSTREAM_VERSION,
openapi_tags=tags_metadata,
openapi_url="/openapi.json",
docs_url=None,
redoc_url=f"/{DOCS_TARGET_PATH}",
)
app.add_middleware(
CORSMiddleware,
allow_origins=ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/", tags=["whales"], response_model=data.GetEventsResponse)
async def stream_handler(
start_time: int = Query(0),
end_time: Optional[int] = Query(None),
include_start: bool = Query(False),
include_end: bool = Query(False),
db_session: Session = Depends(db.yield_db_session),
) -> data.GetEventsResponse:
"""
Retrieves the list of whales spotted over given stream boundary
- **start_time**: Timestamp. Must be provided otherwise this request will hang
- **end_time**: Timestamp. Optional.
- **include_start** (string): is start_time inclusive or not
- **include_end** (string): is end_time inclusive or not
"""
stream_boundary = data.StreamBoundary(
start_time=start_time,
end_time=end_time,
include_start=include_start,
include_end=include_end,
)
result = whalewatch_provider.get_events(
db_session=db_session,
bugout_client=bugout_client,
data_journal_id=MOONSTREAM_DATA_JOURNAL_ID,
data_access_token=MOONSTREAM_ADMIN_ACCESS_TOKEN,
stream_boundary=stream_boundary,
user_subscriptions={whalewatch_provider.event_type: []},
query=StreamQuery(subscription_types=[whalewatch_provider.event_type]),
)
if result is None:
return data.GetEventsResponse(stream_boundary=stream_boundary, events=[])
provider_stream_boundary, events = result
return data.GetEventsResponse(
stream_boundary=provider_stream_boundary, events=events
)

Wyświetl plik

@ -13,6 +13,7 @@ import (
)
var MOONSTREAM_IPC_PATH = os.Getenv("MOONSTREAM_IPC_PATH")
var MOONSTREAM_CORS_ALLOWED_ORIGINS = os.Getenv("MOONSTREAM_CORS_ALLOWED_ORIGINS")
type GethResponse struct {
Result string `json:"result"`
@ -26,8 +27,25 @@ type PingResponse struct {
Status string `json:"status"`
}
// Extends handler with allowed CORS policies
func setupCorsResponse(w *http.ResponseWriter, req *http.Request) {
for _, allowedOrigin := range strings.Split(MOONSTREAM_CORS_ALLOWED_ORIGINS, ",") {
for _, reqOrigin := range req.Header["Origin"] {
if reqOrigin == allowedOrigin {
(*w).Header().Set("Access-Control-Allow-Origin", allowedOrigin)
}
}
}
(*w).Header().Set("Access-Control-Allow-Methods", "GET,OPTIONS")
}
func ping(w http.ResponseWriter, req *http.Request) {
setupCorsResponse(&w, req)
log.Printf("%s, %s, %q", req.RemoteAddr, req.Method, req.URL.String())
if (*req).Method == "OPTIONS" {
return
}
w.Header().Set("Content-Type", "application/json")
response := PingResponse{Status: "ok"}
@ -35,7 +53,11 @@ func ping(w http.ResponseWriter, req *http.Request) {
}
func pingGeth(w http.ResponseWriter, req *http.Request) {
setupCorsResponse(&w, req)
log.Printf("%s, %s, %q", req.RemoteAddr, req.Method, req.URL.String())
if (*req).Method == "OPTIONS" {
return
}
postBody, err := json.Marshal(map[string]interface{}{
"jsonrpc": "2.0",

Wyświetl plik

@ -1,2 +1,3 @@
export MOONSTREAM_CRAWLERS_SERVER_PORT="8080"
export MOONSTREAM_IPC_PATH=null
export MOONSTREAM_CORS_ALLOWED_ORIGINS="http://localhost:3000,https://moonstream.to,https://www.moonstream.to,https://alpha.moonstream.to"

Wyświetl plik

@ -6,12 +6,14 @@ import (
"log"
"net/http"
"os"
"strings"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
var MOONSTREAM_DB_URI = os.Getenv("MOONSTREAM_DB_URI")
var MOONSTREAM_CORS_ALLOWED_ORIGINS = os.Getenv("MOONSTREAM_CORS_ALLOWED_ORIGINS")
type PingResponse struct {
Status string `json:"status"`
@ -21,8 +23,36 @@ type BlockResponse struct {
BlockNumber uint64 `json:"block_number"`
}
var dbConnection *gorm.DB
func InitDB() *gorm.DB {
db, err := gorm.Open(postgres.Open(MOONSTREAM_DB_URI), &gorm.Config{})
if err != nil {
log.Println("Database unavailable")
return nil
}
return db
}
// Extends handler with allowed CORS policies
func setupCorsResponse(w *http.ResponseWriter, req *http.Request) {
for _, allowedOrigin := range strings.Split(MOONSTREAM_CORS_ALLOWED_ORIGINS, ",") {
for _, reqOrigin := range req.Header["Origin"] {
if reqOrigin == allowedOrigin {
(*w).Header().Set("Access-Control-Allow-Origin", allowedOrigin)
}
}
}
(*w).Header().Set("Access-Control-Allow-Methods", "GET,OPTIONS")
}
func ping(w http.ResponseWriter, req *http.Request) {
setupCorsResponse(&w, req)
log.Printf("%s, %s, %q", req.RemoteAddr, req.Method, req.URL.String())
if (*req).Method == "OPTIONS" {
return
}
w.Header().Set("Content-Type", "application/json")
response := PingResponse{Status: "ok"}
@ -30,19 +60,22 @@ func ping(w http.ResponseWriter, req *http.Request) {
}
func blockLatest(w http.ResponseWriter, req *http.Request) {
setupCorsResponse(&w, req)
log.Printf("%s, %s, %q", req.RemoteAddr, req.Method, req.URL.String())
if (*req).Method == "OPTIONS" {
return
}
w.Header().Set("Content-Type", "application/json")
var latestBlock BlockResponse
db, err := gorm.Open(postgres.Open(MOONSTREAM_DB_URI), &gorm.Config{})
if err != nil {
if dbConnection == nil {
http.Error(w, http.StatusText(500), 500)
return
}
query := "SELECT block_number FROM ethereum_blocks ORDER BY block_number DESC LIMIT 1"
db.Raw(query, 1).Scan(&latestBlock.BlockNumber)
dbConnection.Raw(query, 1).Scan(&latestBlock.BlockNumber)
json.NewEncoder(w).Encode(latestBlock)
}
@ -54,6 +87,8 @@ func main() {
flag.StringVar(&listenPort, "port", "8080", "Server listen port")
flag.Parse()
dbConnection = InitDB()
address := listenAddr + ":" + listenPort
log.Printf("Starting server at %s\n", address)

Wyświetl plik

@ -1,2 +1,3 @@
export MOONSTREAM_DB_SERVER_PORT="8080"
export MOONSTREAM_DB_URI="postgresql://<username>:<password>@<db_host>:<db_port>/<db_name>"
export MOONSTREAM_CORS_ALLOWED_ORIGINS="http://localhost:3000,https://moonstream.to,https://www.moonstream.to,https://alpha.moonstream.to"

Wyświetl plik

@ -0,0 +1,263 @@
import React, { useEffect, useState, useLayoutEffect } from "react";
import { useStatus } from "../../src/core/hooks";
import {
Heading,
Text,
Flex,
Spacer,
Stack,
chakra,
useMediaQuery,
useBreakpointValue,
} from "@chakra-ui/react";
import { AWS_ASSETS_PATH } from "../../src/core/constants";
const assets = {
background720: `${AWS_ASSETS_PATH}/product-background-720x405.png`,
background1920: `${AWS_ASSETS_PATH}/product-background-720x405.png`,
background2880: `${AWS_ASSETS_PATH}/product-background-720x405.png`,
background3840: `${AWS_ASSETS_PATH}/product-background-720x405.png`,
};
const Status = () => {
const healthyStatusText = "Available";
const downStatusText = "Unavailable";
const healthyStatusColor = "green.900";
const downStatusColor = "red.600";
const shortTimestamp = (rawTimestamp) => {
return rawTimestamp.replace(/^.+T/, "").replace(/\..+/, "");
};
const {
apiServerStatusCache,
ethereumClusterServerStatusCache,
gethStatusCache,
crawlersStatusCache,
dbServerStatusCache,
latestBlockDBStatusCache,
} = useStatus();
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_ASSETS_PATH}/product-background-720x405.png`;
assets[
"background1920"
] = `${AWS_ASSETS_PATH}/product-background-1920x1080.png`;
assets[
"background2880"
] = `${AWS_ASSETS_PATH}/product-background-2880x1620.png`;
assets[
"background3840"
] = `${AWS_ASSETS_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_ASSETS_PATH}/product-background-720x405.png`;
imageLoader720.onload = () => {
setBackgroundLoaded720(true);
};
}, []);
useLayoutEffect(() => {
const imageLoader1920 = new Image();
imageLoader1920.src = `${AWS_ASSETS_PATH}/product-background-1920x1080.png`;
imageLoader1920.onload = () => {
setBackgroundLoaded1920(true);
};
}, []);
useLayoutEffect(() => {
const imageLoader2880 = new Image();
imageLoader2880.src = `${AWS_ASSETS_PATH}/product-background-2880x1620.png`;
imageLoader2880.onload = () => {
setBackgroundLoaded2880(true);
};
}, []);
useLayoutEffect(() => {
const imageLoader3840 = new Image();
imageLoader3840.src = `${AWS_ASSETS_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"
placeSelf="center"
px={12}
py={2}
borderTopRadius="xl"
>
{`Status page`}
</Heading>
<chakra.span pl={2} px={12} py={2} width="400px">
<Flex mb={3}>
<Text>Backend server</Text>
<Spacer />
<Text
color={
!apiServerStatusCache.isLoading &&
apiServerStatusCache?.data?.status == "ok"
? healthyStatusColor
: downStatusColor
}
>
{!apiServerStatusCache.isLoading &&
apiServerStatusCache?.data?.status == "ok"
? healthyStatusText
: downStatusText}
</Text>
</Flex>
<br />
<Flex mb={3}>
<Text>Crawlers server</Text>
<Spacer />
<Text
color={
!ethereumClusterServerStatusCache.isLoading &&
ethereumClusterServerStatusCache?.data?.status == "ok"
? healthyStatusColor
: downStatusColor
}
>
{!ethereumClusterServerStatusCache.isLoading &&
ethereumClusterServerStatusCache?.data
? healthyStatusText
: downStatusText}
</Text>
</Flex>
<Flex mb={3}>
<Text>Latest block in Geth</Text>
<Spacer />
<Text>
{!gethStatusCache.isLoading &&
gethStatusCache?.data?.current_block
? gethStatusCache.data.current_block
: 0}
</Text>
</Flex>
<Flex mb={3}>
<Text>Txpool latest record ts</Text>
<Spacer />
<Text>
{!crawlersStatusCache.isLoading &&
crawlersStatusCache?.data?.ethereum_txpool_timestamp
? shortTimestamp(
crawlersStatusCache?.data?.ethereum_txpool_timestamp
)
: downStatusText}
</Text>
</Flex>
<Flex mb={3}>
<Text>Trending latest record ts</Text>
<Spacer />
<Text>
{!crawlersStatusCache.isLoading &&
crawlersStatusCache?.data?.ethereum_trending_timestamp
? shortTimestamp(
crawlersStatusCache?.data?.ethereum_trending_timestamp
)
: downStatusText}
</Text>
</Flex>
<br />
<Flex mb={3}>
<Text>Database server</Text>
<Spacer />
<Text
color={
!dbServerStatusCache.isLoading &&
dbServerStatusCache?.data?.status == "ok"
? healthyStatusColor
: downStatusColor
}
>
{!dbServerStatusCache.isLoading &&
dbServerStatusCache?.data?.status == "ok"
? healthyStatusText
: downStatusText}
</Text>
</Flex>
<Flex mb={3}>
<Text>Latest block in Database</Text>
<Spacer />
<Text>
{!latestBlockDBStatusCache.isLoading &&
latestBlockDBStatusCache?.data?.block_number
? latestBlockDBStatusCache.data.block_number
: 0}
</Text>
</Flex>
</chakra.span>
</Stack>
</Flex>
);
};
export default Status;

Wyświetl plik

@ -1,3 +1,5 @@
export NEXT_PUBLIC_MIXPANEL_TOKEN="<YOUR MIXPANEL TOKEN HERE>"
export NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY="<stripe publishable key>"
export NEXT_PUBLIC_MOONSTREAM_API_URL=http://localhost:7481
export NEXT_PUBLIC_MOONSTREAM_API_URL="<moonstream_api_url>"
export NEXT_PUBLIC_MOONSTREAM_ETHEREUM_CLUSTER_URL="<moonstream_crawlers_url>"
export NEXT_PUBLIC_MOONSTREAM_DB_URL="<moonstream_db_url>"

Wyświetl plik

@ -14,6 +14,7 @@ export { default as useQuery } from "./useQuery";
export { default as useResetPassword } from "./useResetPassword";
export { default as useRouter } from "./useRouter";
export { default as useSignUp } from "./useSignUp";
export { default as useStatus } from "./useStatus";
export { default as useStorage } from "./useStorage";
export { default as useStream } from "./useStream";
export { default as useStripe } from "./useStripe";

Wyświetl plik

@ -0,0 +1,68 @@
import { useQuery } from "react-query";
import { queryCacheProps } from "./hookCommon";
import { StatusService } from "../../core/services";
const useStatus = () => {
const getAPIServerStatus = async () => {
const response = await StatusService.apiServerStatus();
return response.data;
};
const getEthereumClusterServerStatus = async () => {
const response = await StatusService.ethereumClusterServerStatus();
return response.data;
};
const getGethStatus = async () => {
const response = await StatusService.gethStatus();
return response.data;
};
const getCrawlersStatus = async () => {
const response = await StatusService.crawlersStatus();
return response.data;
};
const getDBServerStatus = async () => {
const response = await StatusService.dbServerStatus();
return response.data;
};
const getLatestBlockDBStatus = async () => {
const response = await StatusService.latestBlockDBStatus();
return response.data;
};
const apiServerStatusCache = useQuery("apiServer", getAPIServerStatus, {
...queryCacheProps,
});
const ethereumClusterServerStatusCache = useQuery(
"ethereumClusterServer",
getEthereumClusterServerStatus,
{
...queryCacheProps,
}
);
const gethStatusCache = useQuery("geth", getGethStatus, {
...queryCacheProps,
});
const crawlersStatusCache = useQuery("crawlers", getCrawlersStatus, {
...queryCacheProps,
});
const dbServerStatusCache = useQuery("dbServer", getDBServerStatus, {
...queryCacheProps,
});
const latestBlockDBStatusCache = useQuery(
"latestBlockDB",
getLatestBlockDBStatus,
{
...queryCacheProps,
}
);
return {
apiServerStatusCache,
ethereumClusterServerStatusCache,
gethStatusCache,
crawlersStatusCache,
dbServerStatusCache,
latestBlockDBStatusCache,
};
};
export default useStatus;

Wyświetl plik

@ -6,6 +6,7 @@ import * as GroupService from "./group.service";
import * as PreferencesService from "./preferences.service";
import * as HumbugService from "./humbug.service";
import * as InvitesService from "./invites.service";
import * as StatusService from "./status.service";
import * as SubscriptionsService from "./subscriptions.service";
import * as StreamService from "./stream.service";
import * as TxInfoService from "./txinfo.service";
@ -18,6 +19,7 @@ export {
PreferencesService,
HumbugService,
InvitesService,
StatusService,
SubscriptionsService,
StreamService,
TxInfoService,

Wyświetl plik

@ -0,0 +1,48 @@
import { http } from "../utils";
const API_URL = process.env.NEXT_PUBLIC_MOONSTREAM_API_URL;
const DB_URL = process.env.NEXT_PUBLIC_MOONSTREAM_DB_URL;
const ETHEREUM_CLUSTER_URL =
process.env.NEXT_PUBLIC_MOONSTREAM_ETHEREUM_CLUSTER_URL;
export const apiServerStatus = () => {
return http({
method: "GET",
url: `${API_URL}/ping`,
});
};
export const ethereumClusterServerStatus = () => {
return http({
method: "GET",
url: `${ETHEREUM_CLUSTER_URL}/ping`,
});
};
export const gethStatus = () => {
return http({
method: "GET",
url: `${ETHEREUM_CLUSTER_URL}/status`,
});
};
export const crawlersStatus = () => {
return http({
method: "GET",
url: `${API_URL}/status`,
});
};
export const dbServerStatus = () => {
return http({
method: "GET",
url: `${DB_URL}/ping`,
});
};
export const latestBlockDBStatus = () => {
return http({
method: "GET",
url: `${DB_URL}/block/latest`,
});
};