From bf53870b161b8639b42fcda1bda99bbf99e84856 Mon Sep 17 00:00:00 2001 From: Justin Kilpatrick Date: Thu, 9 May 2024 10:09:56 -0400 Subject: [PATCH] Repurpose for Althea L1 info This patch strips out all Gravity specific logic to use this same structure for Althea L1 --- .gitignore | 8 +- README.md | 381 +------ .../.gitignore | 0 .../README.md | 0 .../package.json | 0 .../public/favicon.ico | Bin .../public/index.html | 0 .../public/logo192.png | Bin .../public/logo512.png | Bin .../public/manifest.json | 0 .../public/robots.txt | 0 .../src/App.css | 0 .../src/App.test.tsx | 0 althea-info-dash/src/App.tsx | 88 ++ .../src/index.css | 0 .../src/index.tsx | 0 .../src/react-app-env.d.ts | 0 .../src/reportWebVitals.ts | 0 .../src/setupTests.ts | 0 althea-info-dash/src/types.tsx | 12 + .../tsconfig.json | 0 .../yarn.lock | 0 .../Cargo.lock | 934 +++++------------- .../Cargo.toml | 11 +- althea-info-server/src/main.rs | 119 +++ .../src/tls.rs | 0 .../src/total_suppy.rs | 21 +- gravity-info-dash/src/App.tsx | 441 --------- gravity-info-dash/src/types.tsx | 149 --- gravity-info-server/src/batch_relaying.rs | 98 -- gravity-info-server/src/gravity_info.rs | 484 --------- gravity-info-server/src/main.rs | 233 ----- .../src/transactions/database.rs | 515 ---------- .../src/transactions/endpoints.rs | 342 ------- gravity-info-server/src/transactions/mod.rs | 2 - gravity-info-server/src/volume.rs | 271 ----- scripts/build-and-deploy.sh | 14 +- .../roles/setup-info-server/tasks/main.yml | 6 +- .../roles/setup-info-server/tasks/systemd.yml | 16 +- 39 files changed, 518 insertions(+), 3627 deletions(-) rename {gravity-info-dash => althea-info-dash}/.gitignore (100%) rename {gravity-info-dash => althea-info-dash}/README.md (100%) rename {gravity-info-dash => althea-info-dash}/package.json (100%) rename {gravity-info-dash => althea-info-dash}/public/favicon.ico (100%) rename {gravity-info-dash => althea-info-dash}/public/index.html (100%) rename {gravity-info-dash => althea-info-dash}/public/logo192.png (100%) rename {gravity-info-dash => althea-info-dash}/public/logo512.png (100%) rename {gravity-info-dash => althea-info-dash}/public/manifest.json (100%) rename {gravity-info-dash => althea-info-dash}/public/robots.txt (100%) rename {gravity-info-dash => althea-info-dash}/src/App.css (100%) rename {gravity-info-dash => althea-info-dash}/src/App.test.tsx (100%) create mode 100644 althea-info-dash/src/App.tsx rename {gravity-info-dash => althea-info-dash}/src/index.css (100%) rename {gravity-info-dash => althea-info-dash}/src/index.tsx (100%) rename {gravity-info-dash => althea-info-dash}/src/react-app-env.d.ts (100%) rename {gravity-info-dash => althea-info-dash}/src/reportWebVitals.ts (100%) rename {gravity-info-dash => althea-info-dash}/src/setupTests.ts (100%) create mode 100644 althea-info-dash/src/types.tsx rename {gravity-info-dash => althea-info-dash}/tsconfig.json (100%) rename {gravity-info-dash => althea-info-dash}/yarn.lock (100%) rename {gravity-info-server => althea-info-server}/Cargo.lock (77%) rename {gravity-info-server => althea-info-server}/Cargo.toml (51%) create mode 100644 althea-info-server/src/main.rs rename {gravity-info-server => althea-info-server}/src/tls.rs (100%) rename {gravity-info-server => althea-info-server}/src/total_suppy.rs (96%) delete mode 100644 gravity-info-dash/src/App.tsx delete mode 100644 gravity-info-dash/src/types.tsx delete mode 100644 gravity-info-server/src/batch_relaying.rs delete mode 100644 gravity-info-server/src/gravity_info.rs delete mode 100644 gravity-info-server/src/main.rs delete mode 100644 gravity-info-server/src/transactions/database.rs delete mode 100644 gravity-info-server/src/transactions/endpoints.rs delete mode 100644 gravity-info-server/src/transactions/mod.rs delete mode 100644 gravity-info-server/src/volume.rs diff --git a/.gitignore b/.gitignore index 5d44e8c..181b6dc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -gravity-info-server/target/* -scripts/gravity-info-server -scripts/gravity-info-dash/* -gravity-info-server/transactions \ No newline at end of file +althea-info-server/target/* +scripts/althea-info-server +scripts/althea-info-dash/* +althea-info-server/transactions \ No newline at end of file diff --git a/README.md b/README.md index 2537146..4642310 100644 --- a/README.md +++ b/README.md @@ -1,265 +1,24 @@ -# Gravity Info Dashboard +# Althea L1 Info Dashboard -This repo contains frontend and backend code for deploying a Gravity information server, this server queries public full nodes and processes data about the chain in order to present the page https://info.gravitychain.io in addition to this page public API endpoints are provided +This repo contains frontend and backend code for deploying a Althea L1 information server, this server queries public full nodes and processes data about the chain in order to present the page https://info.althea.link in addition to this page public API endpoints are provided -This server computes and displays info that would be otherwise difficult to access or compute. Such as daily and weekly bridge volume, vesting info, and parsed out transfer destinations. +This server computes and displays info that would be otherwise difficult to access or compute. Such as token supply metrics + +TODO: +MicroTx volume +EVM transaction fee volume Issues and pull requests for new endpoints or information formats are welcome. -The repo auto-deploys the most recent commit in main to https://info.gravitychain.io +The repo auto-deploys the most recent commit in main to https://info.althea.link ## API Docs -### /bridge_volume - -Provides monthly, weekly, and daily volume information for [Gravity Bridge](https://etherscan.io/address/0xa4108aA1Ec4967F8b52220a4f7e94A8201F2D906#tokentxns). The value of all bridged tokens is converted to USDC and summed. Units here are in whole USDC. This endpoint is updated once a day. - -- URL: `https://info.gravitychain.io:9000/bridge_volume` -- Method: `GET` -- URL Params: `None` -- Data Params: `None` -- Success Response: - - Code: 200 OK - - Contents: - -``` -{ - "daily_volume": 21220096.012809116, - "daily_inflow": 20476817.14186712, - "daily_outflow": 743278.8709419968, - "weekly_volume": 45889152.25069955, - "weekly_inflow": 38810900.95307093, - "weekly_outflow": 7078251.297628619, - "monthly_volume": 48873709.034694746, - "monthly_inflow": 21492436.59797602, - "monthly_outflow": 27381272.43671871 -} -``` - -- Error Response: `500 Server Error` - -- Sample Call: - -`curl https://info.gravitychain.io:9000/bridge_volume` - ---- - -### /erc20_metadata - -Provides a list of every ERC20 that is in the [Gravity Bridge solidity contract](https://etherscan.io/address/0xa4108aA1Ec4967F8b52220a4f7e94A8201F2D906#tokentxns) along with symbol + decimals metadata. If this ERC20 has a Uniswap v2 or v3 pair an exchange rate is provided. The exchange rate is the amount of USDC 1 unit of the input token would buy. For example UNI below has a value of `"exchange_rate": "7259165"` meaning 1 UNI is worth `7259165` base units of USDC. Since USDC is a 6 decimal token we divide by `1*10^6` and get $7.25. This endpoint is updated every 30 seconds and does not rate limit queries. - -- URL: `https://info.gravitychain.io:9000/erc20_metadata` -- Method: `GET` -- URL Params: `None` -- Data Params: `None` -- Success Response: - - Code: 200 OK - - Contents: - -``` -[ - { - "address": "0x147faF8De9d8D8DAAE129B187F0D02D819126750", - "decimals": "18", - "symbol": "GEO", - "exchange_rate": null - }, - { - "address": "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984", - "decimals": "18", - "symbol": "UNI", - "exchange_rate": "7259165" - }, -] - - -``` - -- Error Response: `500 Server Error` - -- Sample Call: - -`curl https://info.gravitychain.io:9000/erc20_metadata` - ---- - -### /gravity_bridge_info - -Provides info about the state of the Gravity Bridge module. Including the batch queue going out to Ethereum and the oracle bringing events in from Ethereum. This is updated every 30 seconds and ther is no rate limit on querying. - -- URL: `https://info.gravitychain.io:9000/gravity_bridge_info` -- Method: `GET` -- URL Params: `None` -- Data Params: `None` -- Success Response: - - Code: 200 OK - - Contents: - -``` -{ - "pending_tx": [ - { - "token": "0xe9B076B476D8865cDF79D1Cf7DF420EE397a7f75", - "total_fees": "10000000000", - "tx_count": 1 - } - ], - "pending_batches": [ - { - "nonce": 6388, - "batch_timeout": 15876299, - "transactions": [ - { - "id": 7153, - "sender": "gravity1eppzhlpczlap8he2h95yedzrwm96496c0hup0g", - "destination": "0xC7172CeD2d1BE642bad2dC051A208F6cFC89aEa0", - "erc20_token": { - "amount": "6000000", - "contract": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" - }, - "erc20_fee": { - "amount": "6385782", - "contract": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" - } - } - ], - "total_fee": { - "amount": "16406414", - "contract": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" - }, - "token_contract": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" - } - ], - "attestations": [ - { - "height": 4303597, - "observed": true, - "votes": 146 - } - ], - "params": { - "bridge_ethereum_address": "0xa4108aA1Ec4967F8b52220a4f7e94A8201F2D906", - "average_block_time": 6282, - "average_ethereum_block_time": 12020, - "target_batch_timeout": 7200000, - "bridge_active": true, - "ethereum_blacklist": [ - "0x8576aCC5C05D6Ce88f4e49bf65BdF0C62F91353C", - ], - "gravity_id": "gravity-bridge-mainnet", - "bridge_chain_id": 1, - "signed_valsets_window": 10000, - "signed_batches_window": 10000, - "signed_logic_calls_window": 10000, - "unbond_slashing_valsets_window": 10000, - "valset_reward": { - "amount": "0", - "denom": "" - }, - "min_chain_fee_basis_points": 2 - } - -} -``` - -- Error Response: `500 Server Error` - -- Sample Call: - -`curl https://info.gravitychain.io:9000/gravity_bridge_info` - ---- - - -### /eth_bridge_info - -Provides parsed Ethereum events from the [Gravity Bridge solidity contract](https://etherscan.io/address/0xa4108aA1Ec4967F8b52220a4f7e94A8201F2D906#tokentxns). This events list is updated every 30 seconds and there is no rate limit on querying. - -- URL: `https://info.gravitychain.io:9000/eth_bridge_info` -- Method: `GET` -- URL Params: `None` -- Data Params: `None` -- Success Response: - - Code: 200 OK - - Contents: - -``` -{ - "deposit_events": [ - { - "erc20": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", - "sender": "0xb5e452a90280A978aA8DAe4306F960167c7C528A", - "destination": "canto1khj992gzsz5h325d4epsd7tqze78c552gc870p", - "amount": "200000000000000000", - "event_nonce": 19443, - "block_height": "15876508", - "confirmed": true, - "blocks_until_confirmed": "0", - "seconds_until_confirmed": "0" - }, - { - "erc20": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", - "sender": "0xFe9707E8d9B9436f99633987b400bbdf6a5Ab072", - "destination": "canto1l6ts06xeh9pklxtr8xrmgq9mma494vrjrr6pjf", - "amount": "340000000000000000", - "event_nonce": 19444, - "block_height": "15876578", - "confirmed": false, - "blocks_until_confirmed": "14", - "seconds_until_confirmed": "168" - }, - ], - "batch_events": [ - { - "batch_nonce": 6312, - "block_height": "15869111", - "erc20": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", - "event_nonce": 19315 - } - ], - "valset_updates": [ - { - "valset_nonce": 796, - "event_nonce": 19428, - "block_height": "15875929", - "reward_amount": "0", - "reward_token": null, - "members": [ - { - "power": 504447949, - "eth_address": "0x30d19C8a86C07991328C83FDB571A0De90A7290c" - } - ] - } - ], - "erc20_deploys": [ - { - "cosmos_denom": "ibc/D157AD8A50DAB0FC4EB95BBE1D9407A590FA2CDEE04C90A76C005089BF76E519", - "erc20_address": "0xe9B076B476D8865cDF79D1Cf7DF420EE397a7f75", - "name": "Unification", - "symbol": "FUND", - "decimals": 9, - "event_nonce": 19411, - "block_height": "15875392" - }, - ], - "logic_calls": [] - -``` - -- Error Response: `500 Server Error` - -- Sample Call: - -`curl https://info.gravitychain.io:9000/eth_bridge_info` - ---- - ### /total_supply Provides the total supply of GRAV, or any Cosmos chain the server software is pointed at. This is inclusive of the community pool, vesting tokens, staked tokens, and unclaimed rewards. Value return is ugravition and must be divided by `1*10^6` to display whole tokens. This value is updated once a day. -- URL: `https://info.gravitychain.io:9000/total_supply` +- URL: `https://info.althea.link:9000/total_supply` - Method: `GET` - URL Params: `None` - Data Params: `None` @@ -275,7 +34,7 @@ Provides the total supply of GRAV, or any Cosmos chain the server software is po - Sample Call: -`curl https://info.gravitychain.io:9000/total_supply` +`curl https://info.althea.link:9000/total_supply` --- @@ -283,7 +42,7 @@ Provides the total supply of GRAV, or any Cosmos chain the server software is po Provides the total liquid supply of GRAV, or any Cosmos chain the server software is pointed at. Liquid supply excludes only module tokens and vesting tokens. Staked tokens and unclaimed rewards count in the total. Value return is ugravition and must be divided by `1*10^6` to display whole tokens. This value is updated once a day. -- URL: `https://info.gravitychain.io:9000/total_liquid_supply` +- URL: `https://info.althea.link:9000/total_liquid_supply` - Method: `GET` - URL Params: `None` - Data Params: `None` @@ -299,7 +58,7 @@ Provides the total liquid supply of GRAV, or any Cosmos chain the server softwar - Sample Call: -`curl https://info.gravitychain.io:9000/total_liquid_supply` +`curl https://info.althea.link:9000/total_liquid_supply` --- @@ -316,7 +75,7 @@ Provides a breakdown of vesting versus non-vesting tokens for Gravity Bridge, va * total_vesting_staked: All tokens that are vesting and also staked * total_vested: The amount of tokens that where once vesting but are now liquid -- URL: `https://info.gravitychain.io:9000/supply_info` +- URL: `https://info.althea.link:9000/supply_info` - Method: `GET` - URL Params: `None` - Data Params: `None` @@ -344,116 +103,6 @@ Provides a breakdown of vesting versus non-vesting tokens for Gravity Bridge, va - Sample Call: -`curl https://info.gravitychain.io:9000/supply_info` - ---- - -### /transactions - -Provides Gravity Bridge transaction info. Currently two message types are supported **MsgSendToEth** & **MsgTransfer**. - -**MsgSendToEth** is the message type used to bridge assets from the Cosmos side to Ethereum. -- URL: `https://info.gravitychain.io:9000/transactions/send_to_eth` -- Method: `GET` -- URL Params: `None` -- Data Params: `None` -- Success Response: - - Code: 200 OK - - Contents: - -``` - { - "tx_hash": "9EA7C11DB18B87111E2679F3FFACC2B0C77135C60A05B7836F404B5F93EF7D18", - "data": { - "amount": [ - { - "amount": "89200000000000000", - "denom": "gravity0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" - } - ], - "bridge_fee": [ - { - "amount": "3200000000000000", - "denom": "gravity0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" - } - ], - "chain_fee": [], - "eth_dest": "0xf0f08f640d5553e79b91296dba6c3f10521e5174", - "sender": "gravity1xq7j6pr0zphuq6elxmrg98zkm57u36pvz2uwcc" - } - } -``` - -- Error Response: `500 Server Error` - -- Sample Call: - -`curl https://info.gravitychain.io:9000/transactions/send_to_eth` - -**MsgTransfer** is the message type used to transfer assets in between IBC enabled Cosmos chains. - -- URL: `https://info.gravitychain.io:9000/transactions/ibc_transfer` -- Method: `GET` -- URL Params: `None` -- Data Params: `None` -- Success Response: - - Code: 200 OK - - Contents: - -``` - { - "tx_hash": "0000405E464C64DE8537B594742CBD9D7E0AD8EEFDB118158AC4582FFE101A10", - "data": { - "receiver": "persistence1ac05mw63eury6arcux7u2qtxwxq68qvefxqczm", - "sender": "gravity1apkwuud8qdkw3nectycl7d46j5jvqs4kq8nhhf", - "source_channel": "channel-24", - "source_port": "transfer", - "timeout_height": { - "revision_height": 4954551, - "revision_number": 1 - }, - "timeout_timestamp": 0, - "token": [ - { - "amount": "150000000000000000000", - "denom": "gravity0xfB5c6815cA3AC72Ce9F5006869AE67f18bF77006" - } - ] - } - } -``` - -- Error Response: `500 Server Error` - -- Sample Call: - -`curl https://info.gravitychain.io:9000/transactions/ibc_transfer` - ---- - -### /batch_tx/{batch_nonce} - -Takes the url encoded batch nonce as a request value and builds the required ETH transaction payload to relay this batch. -Note the return value of this endpoint is the 'data' field of the Ethereum transaction. The rest of the transaction is up -to your application to fill out and send. - -**MsgSendToEth** is the message type used to bridge assets from the Cosmos side to Ethereum. -- URL: `https://info.gravitychain.io:9000/batch_tx/{batch_nonce}` -- Method: `GET` -- URL Params: `None` -- Data Params: `None` -- Success Response: - - Code: 200 OK - - Contents: - -``` -{ - [82,93...] -} -``` - -- Error Response: `500 Server Error` - -- Sample Call: +`curl https://info.althea.link:9000/supply_info` -`curl https://info.gravitychain.io:9000/batch_tx/123456` \ No newline at end of file +--- \ No newline at end of file diff --git a/gravity-info-dash/.gitignore b/althea-info-dash/.gitignore similarity index 100% rename from gravity-info-dash/.gitignore rename to althea-info-dash/.gitignore diff --git a/gravity-info-dash/README.md b/althea-info-dash/README.md similarity index 100% rename from gravity-info-dash/README.md rename to althea-info-dash/README.md diff --git a/gravity-info-dash/package.json b/althea-info-dash/package.json similarity index 100% rename from gravity-info-dash/package.json rename to althea-info-dash/package.json diff --git a/gravity-info-dash/public/favicon.ico b/althea-info-dash/public/favicon.ico similarity index 100% rename from gravity-info-dash/public/favicon.ico rename to althea-info-dash/public/favicon.ico diff --git a/gravity-info-dash/public/index.html b/althea-info-dash/public/index.html similarity index 100% rename from gravity-info-dash/public/index.html rename to althea-info-dash/public/index.html diff --git a/gravity-info-dash/public/logo192.png b/althea-info-dash/public/logo192.png similarity index 100% rename from gravity-info-dash/public/logo192.png rename to althea-info-dash/public/logo192.png diff --git a/gravity-info-dash/public/logo512.png b/althea-info-dash/public/logo512.png similarity index 100% rename from gravity-info-dash/public/logo512.png rename to althea-info-dash/public/logo512.png diff --git a/gravity-info-dash/public/manifest.json b/althea-info-dash/public/manifest.json similarity index 100% rename from gravity-info-dash/public/manifest.json rename to althea-info-dash/public/manifest.json diff --git a/gravity-info-dash/public/robots.txt b/althea-info-dash/public/robots.txt similarity index 100% rename from gravity-info-dash/public/robots.txt rename to althea-info-dash/public/robots.txt diff --git a/gravity-info-dash/src/App.css b/althea-info-dash/src/App.css similarity index 100% rename from gravity-info-dash/src/App.css rename to althea-info-dash/src/App.css diff --git a/gravity-info-dash/src/App.test.tsx b/althea-info-dash/src/App.test.tsx similarity index 100% rename from gravity-info-dash/src/App.test.tsx rename to althea-info-dash/src/App.test.tsx diff --git a/althea-info-dash/src/App.tsx b/althea-info-dash/src/App.tsx new file mode 100644 index 0000000..082eddc --- /dev/null +++ b/althea-info-dash/src/App.tsx @@ -0,0 +1,88 @@ +import React, { useEffect, useState } from 'react'; +import 'bootstrap/dist/css/bootstrap.min.css'; +import './App.css'; +import { + Spinner, + CardBody, + CardTitle, + Card, + CardSubtitle, + Table, +} from "reactstrap"; +import { ChainTotalSupplyNumbers } from './types'; +// 5 seconds +const UPDATE_TIME = 5000; + +const BACKEND_PORT = 9000; +export const SERVER_URL = + "https://" + window.location.hostname + ":" + BACKEND_PORT + "/"; + +function App() { + document.title = "Althea L1 Info" + const [supplyInfo, setSupplyInfo] = useState(null); + + async function getDistributionInfo() { + let request_url = SERVER_URL + "supply_info"; + const requestOptions: any = { + method: "GET", + headers: { + Accept: "application/json", + "Content-Type": "application/json", + }, + }; + + const result = await fetch(request_url, requestOptions); + const json = await result.json(); + setSupplyInfo(json) + } + + + useEffect(() => { + getDistributionInfo(); + //eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + useEffect(() => { + const interval = setInterval(() => { + getDistributionInfo(); + }, UPDATE_TIME); + return () => clearInterval(interval); + //eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + if (supplyInfo == null || typeof (supplyInfo) === "string") { + return ( +
+ + Loading... + +
+ ) + } + + return ( +
+
+ + + + Gravity Supply Info + +
Total Supply: {(supplyInfo.total_supply / 10 ** 24).toFixed(2)}M ALTHEA
+
Community Pool: {(supplyInfo.community_pool / 10 ** 24).toFixed(2)}M ALTHEA
+
Liquid (Not Vesting): {(supplyInfo.total_liquid_supply / 10 ** 24).toFixed(2)}M ALTHEA
+
Liquid (Not Vesting) and staked: {(supplyInfo.total_nonvesting_staked / 10 ** 24).toFixed(2)}M ALTHEA
+
Unclaimed staking rewards: {(supplyInfo.total_unclaimed_rewards / 10 ** 24).toFixed(2)}M ALTHEA
+
Unvested: {(supplyInfo.total_vesting / 10 ** 24).toFixed(2)}M ALTHEA
+
Unvested Staked: {(supplyInfo.total_vesting_staked / 10 ** 24).toFixed(2)}M ALTHEA
+
Vested: {(supplyInfo.total_vested / 10 ** 24).toFixed(2)}M ALTHEA
+
+
+
+
+ ); +} + +export default App; \ No newline at end of file diff --git a/gravity-info-dash/src/index.css b/althea-info-dash/src/index.css similarity index 100% rename from gravity-info-dash/src/index.css rename to althea-info-dash/src/index.css diff --git a/gravity-info-dash/src/index.tsx b/althea-info-dash/src/index.tsx similarity index 100% rename from gravity-info-dash/src/index.tsx rename to althea-info-dash/src/index.tsx diff --git a/gravity-info-dash/src/react-app-env.d.ts b/althea-info-dash/src/react-app-env.d.ts similarity index 100% rename from gravity-info-dash/src/react-app-env.d.ts rename to althea-info-dash/src/react-app-env.d.ts diff --git a/gravity-info-dash/src/reportWebVitals.ts b/althea-info-dash/src/reportWebVitals.ts similarity index 100% rename from gravity-info-dash/src/reportWebVitals.ts rename to althea-info-dash/src/reportWebVitals.ts diff --git a/gravity-info-dash/src/setupTests.ts b/althea-info-dash/src/setupTests.ts similarity index 100% rename from gravity-info-dash/src/setupTests.ts rename to althea-info-dash/src/setupTests.ts diff --git a/althea-info-dash/src/types.tsx b/althea-info-dash/src/types.tsx new file mode 100644 index 0000000..9289b10 --- /dev/null +++ b/althea-info-dash/src/types.tsx @@ -0,0 +1,12 @@ + +export type ChainTotalSupplyNumbers = { + community_pool: number, + total_supply: number, + total_liquid_supply: number, + total_liquid_balances: number, + total_unclaimed_rewards: number, + total_nonvesting_staked: number, + total_vesting: number, + total_vesting_staked: number, + total_vested: number, +} \ No newline at end of file diff --git a/gravity-info-dash/tsconfig.json b/althea-info-dash/tsconfig.json similarity index 100% rename from gravity-info-dash/tsconfig.json rename to althea-info-dash/tsconfig.json diff --git a/gravity-info-dash/yarn.lock b/althea-info-dash/yarn.lock similarity index 100% rename from gravity-info-dash/yarn.lock rename to althea-info-dash/yarn.lock diff --git a/gravity-info-server/Cargo.lock b/althea-info-server/Cargo.lock similarity index 77% rename from gravity-info-server/Cargo.lock rename to althea-info-server/Cargo.lock index a3eaa17..a829a2f 100644 --- a/gravity-info-server/Cargo.lock +++ b/althea-info-server/Cargo.lock @@ -8,7 +8,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "bytes", "futures-core", "futures-sink", @@ -47,7 +47,7 @@ dependencies = [ "actix-utils", "ahash 0.8.11", "base64 0.21.7", - "bitflags 2.4.2", + "bitflags 2.5.0", "brotli", "bytes", "bytestring", @@ -81,7 +81,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.52", + "syn 2.0.61", ] [[package]] @@ -219,7 +219,7 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.61", ] [[package]] @@ -263,9 +263,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -285,6 +285,38 @@ dependencies = [ "alloc-no-stdlib", ] +[[package]] +name = "althea-info-server" +version = "0.1.0" +dependencies = [ + "actix-cors", + "actix-rt", + "actix-web", + "chrono", + "clarity", + "cosmos-sdk-proto-althea", + "deep_space", + "env_logger", + "futures", + "hex", + "json", + "lazy_static", + "log", + "num256", + "openssl-probe", + "prost-types", + "rust_decimal", + "rustls 0.20.9", + "rustls-pemfile 0.3.0", + "serde", + "serde_derive", + "serde_json", + "sha256", + "tokio", + "tonic", + "web30", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -302,47 +334,48 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -350,9 +383,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.81" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" +checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" [[package]] name = "arrayvec" @@ -379,36 +412,25 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.61", ] [[package]] name = "async-trait" -version = "0.1.77" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", + "syn 2.0.61", ] [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "awc" @@ -490,9 +512,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -521,26 +543,6 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" -[[package]] -name = "bindgen" -version = "0.69.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" -dependencies = [ - "bitflags 2.4.2", - "cexpr", - "clang-sys", - "itertools 0.12.1", - "lazy_static", - "lazycell", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.52", -] - [[package]] name = "bitflags" version = "1.3.2" @@ -549,9 +551,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "bitvec" @@ -585,9 +587,9 @@ dependencies = [ [[package]] name = "borsh" -version = "1.3.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58b559fd6448c6e2fd0adb5720cd98a2506594cafa4737ff98c396f3e82f667" +checksum = "dbe5b10e214954177fb1dc9fbd20a1a2608fe99e6c832033bdc7cea287a20d77" dependencies = [ "borsh-derive", "cfg_aliases", @@ -595,23 +597,23 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "1.3.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aadb5b6ccbd078890f6d7003694e33816e6b784358f18e15e7e6d9f065a57cd" +checksum = "d7a8646f94ab393e43e8b35a2558b1624bed28b97ee09c5d15456e3c9463f46d" dependencies = [ "once_cell", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.61", "syn_derive", ] [[package]] name = "brotli" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f" +checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -630,9 +632,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.15.4" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytecheck" @@ -658,9 +660,9 @@ dependencies = [ [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "bytestring" @@ -671,34 +673,15 @@ dependencies = [ "bytes", ] -[[package]] -name = "bzip2-sys" -version = "0.1.11+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - [[package]] name = "cc" -version = "1.0.90" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" dependencies = [ "jobserver", "libc", -] - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", + "once_cell", ] [[package]] @@ -715,34 +698,23 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" [[package]] name = "chrono" -version = "0.4.35" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", - "windows-targets 0.52.4", -] - -[[package]] -name = "clang-sys" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" -dependencies = [ - "glob", - "libc", - "libloading", + "windows-targets 0.52.5", ] [[package]] name = "clarity" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "273c656822c0367587c0fc6ae5a0bf6e19a10d700cd49168a084975b7f84dcfe" +checksum = "4cc231e36d58a7fc35e59d4177f5579428e3586992f93ebabeafb873ef89eb46" dependencies = [ "num-traits", "num256", @@ -754,9 +726,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "convert_case" @@ -793,40 +765,15 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cosmos-sdk-proto-althea" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46ab2605efe920646aac126cebdab37648f7fd344c17f90ce71aab58ac62783d" +checksum = "02749095f4edf5ecb676a2a77a8ed0b2198a14ef0a5f819fd6ec15841a40c27f" dependencies = [ "prost", "prost-types", "tonic", ] -[[package]] -name = "cosmos_gravity" -version = "0.1.0" -source = "git+https://github.com/gravity-bridge/gravity-bridge?rev=34fde72dd63eb08d01d43fdcc1cfff86e87b3be7#34fde72dd63eb08d01d43fdcc1cfff86e87b3be7" -dependencies = [ - "bytes", - "clarity", - "deep_space", - "ethereum_gravity", - "gravity_proto", - "gravity_utils", - "log", - "num", - "num256", - "prost", - "prost-types", - "serde", - "serde_derive", - "serde_json", - "sha3", - "tokio", - "tonic", - "web30", -] - [[package]] name = "cpufeatures" version = "0.2.12" @@ -857,9 +804,9 @@ dependencies = [ [[package]] name = "deep_space" -version = "2.23.3" +version = "2.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d328025c921c4041231fe541711c0396ef4a39d8c86d51220b2595ca9b29f34" +checksum = "96c702be76d65f74ea018a5fba52d78712e7fec9e2a5915261452bab5c097c00" dependencies = [ "base64 0.21.7", "bech32", @@ -918,29 +865,17 @@ dependencies = [ "subtle", ] -[[package]] -name = "docopt" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f3f119846c823f9eafcf953a8f6ffb6ed69bf6240883261a7f13b634579a51f" -dependencies = [ - "lazy_static", - "regex", - "serde", - "strsim", -] - [[package]] name = "either" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if", ] @@ -955,32 +890,6 @@ dependencies = [ "regex", ] -[[package]] -name = "env_logger" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" -dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", -] - -[[package]] -name = "env_logger" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" -dependencies = [ - "humantime", - "is-terminal", - "log", - "regex", - "termcolor", -] - [[package]] name = "env_logger" version = "0.11.3" @@ -1000,25 +909,11 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" -[[package]] -name = "ethereum_gravity" -version = "0.1.0" -source = "git+https://github.com/gravity-bridge/gravity-bridge?rev=34fde72dd63eb08d01d43fdcc1cfff86e87b3be7#34fde72dd63eb08d01d43fdcc1cfff86e87b3be7" -dependencies = [ - "clarity", - "deep_space", - "gravity_utils", - "log", - "num256", - "sha3", - "web30", -] - [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" dependencies = [ "crc32fast", "miniz_oxide", @@ -1116,7 +1011,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.61", ] [[package]] @@ -1161,9 +1056,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -1176,91 +1071,11 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[package]] -name = "gravity-info-server" -version = "0.1.0" -dependencies = [ - "actix-cors", - "actix-rt", - "actix-web", - "chrono", - "clarity", - "cosmos-sdk-proto-althea", - "cosmos_gravity", - "deep_space", - "env_logger 0.11.3", - "ethereum_gravity", - "futures", - "gravity_proto", - "gravity_utils", - "hex", - "json", - "jsonrpc_server", - "lazy_static", - "log", - "num256", - "openssl-probe", - "prost-types", - "relayer", - "rocksdb", - "rust_decimal", - "rustls 0.20.9", - "rustls-pemfile 0.3.0", - "serde", - "serde_derive", - "serde_json", - "sha256", - "tokio", - "tonic", - "web30", -] - -[[package]] -name = "gravity_proto" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f55505edecf612bb2269e9e70e294f8f102b7421c2f61da4c3476f02342300d" -dependencies = [ - "cosmos-sdk-proto-althea", - "prost", - "prost-types", - "tonic", -] - -[[package]] -name = "gravity_utils" -version = "0.1.0" -source = "git+https://github.com/gravity-bridge/gravity-bridge?rev=34fde72dd63eb08d01d43fdcc1cfff86e87b3be7#34fde72dd63eb08d01d43fdcc1cfff86e87b3be7" -dependencies = [ - "clarity", - "deep_space", - "futures", - "gravity_proto", - "lazy_static", - "log", - "num-bigint", - "num-traits", - "num256", - "serde", - "serde_derive", - "sha3", - "tokio", - "tonic", - "url", - "web30", -] - [[package]] name = "h2" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", @@ -1268,7 +1083,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.2.5", + "indexmap 2.2.6", "slab", "tokio", "tokio-util", @@ -1286,18 +1101,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hermit-abi" @@ -1458,33 +1264,19 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.5" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.3", -] - -[[package]] -name = "is-terminal" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" -dependencies = [ - "hermit-abi 0.3.9", - "libc", - "windows-sys 0.52.0", + "hashbrown 0.14.5", ] [[package]] -name = "itertools" -version = "0.11.0" +name = "is_terminal_polyfill" +version = "1.70.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" [[package]] name = "itertools" @@ -1497,15 +1289,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" -version = "0.1.28" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" +checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" dependencies = [ "libc", ] @@ -1525,33 +1317,6 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd" -[[package]] -name = "jsonrpc_server" -version = "0.1.0" -source = "git+https://github.com/gravity-bridge/gravity-bridge?rev=34fde72dd63eb08d01d43fdcc1cfff86e87b3be7#34fde72dd63eb08d01d43fdcc1cfff86e87b3be7" -dependencies = [ - "actix-cors", - "actix-rt", - "actix-web", - "chrono", - "env_logger 0.9.3", - "futures", - "hex", - "json", - "lazy_static", - "log", - "mime", - "num256", - "openssl-probe", - "rust_decimal", - "rustls 0.20.9", - "rustls-pemfile 0.3.0", - "serde", - "serde_json", - "sha256", - "tokio", -] - [[package]] name = "keccak" version = "0.1.5" @@ -1573,54 +1338,11 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - [[package]] name = "libc" -version = "0.2.153" +version = "0.2.154" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" - -[[package]] -name = "libloading" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" -dependencies = [ - "cfg-if", - "windows-targets 0.52.4", -] - -[[package]] -name = "librocksdb-sys" -version = "0.16.0+8.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce3d60bc059831dc1c83903fb45c103f75db65c5a7bf22272764d9cc683e348c" -dependencies = [ - "bindgen", - "bzip2-sys", - "cc", - "glob", - "libc", - "libz-sys", - "lz4-sys", - "zstd-sys", -] - -[[package]] -name = "libz-sys" -version = "1.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037731f5d3aaa87a5675e895b63ddff1a87624bc29f77004ea829809654e48f6" -dependencies = [ - "cc", - "pkg-config", - "vcpkg", -] +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" [[package]] name = "local-channel" @@ -1641,9 +1363,9 @@ checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -1655,16 +1377,6 @@ version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" -[[package]] -name = "lz4-sys" -version = "1.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d27b317e207b10f69f5e75494119e391a96f48861ae870d1da6edac98ca900" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "matchit" version = "0.7.3" @@ -1673,9 +1385,9 @@ checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "mime" @@ -1683,12 +1395,6 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - [[package]] name = "miniz_oxide" version = "0.7.2" @@ -1710,102 +1416,26 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "num" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-complex" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" -dependencies = [ - "num-traits", -] - [[package]] name = "num-conv" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg", - "num-bigint", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] [[package]] name = "num256" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27dd9df2c73f8724f4f6930882c127f042656bc84e6000fe9f6026bb43fe1a57" +checksum = "ac4d0cdb15f1e6bf76376510d4c2c6b059df1449f2e3717367988460f2467404" dependencies = [ "bnum", "num-traits", @@ -1818,7 +1448,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.9", + "hermit-abi", "libc", ] @@ -1843,7 +1473,7 @@ version = "0.10.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "cfg-if", "foreign-types", "libc", @@ -1860,7 +1490,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.61", ] [[package]] @@ -1871,9 +1501,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.101" +version = "0.9.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dda2b0f344e78efc2facf7d195d098df0dd72151b26ab98da807afc26c198dff" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" dependencies = [ "cc", "libc", @@ -1883,9 +1513,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" dependencies = [ "lock_api", "parking_lot_core", @@ -1893,22 +1523,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.5", ] [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pbkdf2" @@ -1943,14 +1573,14 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.61", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -2010,18 +1640,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" dependencies = [ "unicode-ident", ] [[package]] name = "prost" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" +checksum = "d0f5d036824e4761737860779c906171497f6d55681139d8312388f8fe398922" dependencies = [ "bytes", "prost-derive", @@ -2029,22 +1659,22 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.12.3" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" +checksum = "9554e3ab233f0a932403704f1a1d08c30d5ccd931adfdfa1e8b5a19b52c1d55a" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.61", ] [[package]] name = "prost-types" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" +checksum = "3235c33eb02c1f1e212abdbe34c78b264b038fb58ca612664343271e36e55ffe" dependencies = [ "prost", ] @@ -2071,9 +1701,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -2116,18 +1746,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", ] [[package]] name = "regex" -version = "1.10.3" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", @@ -2148,35 +1778,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - -[[package]] -name = "relayer" -version = "0.4.3" -source = "git+https://github.com/gravity-bridge/gravity-bridge?rev=34fde72dd63eb08d01d43fdcc1cfff86e87b3be7#34fde72dd63eb08d01d43fdcc1cfff86e87b3be7" -dependencies = [ - "actix-rt", - "clarity", - "cosmos_gravity", - "deep_space", - "docopt", - "env_logger 0.10.2", - "ethereum_gravity", - "futures", - "gravity_proto", - "gravity_utils", - "lazy_static", - "log", - "num256", - "openssl-probe", - "serde", - "serde_derive", - "tokio", - "tonic", - "web30", -] +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "rend" @@ -2255,21 +1859,11 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "rocksdb" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bd13e55d6d7b8cd0ea569161127567cd587676c99f4472f779a0279aa60a7a7" -dependencies = [ - "libc", - "librocksdb-sys", -] - [[package]] name = "rust_decimal" -version = "1.34.3" +version = "1.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39449a79f45e8da28c57c341891b69a183044b29518bb8f86dbac9df60bb7df" +checksum = "1790d1c4c0ca81211399e0e0af16333276f375209e71a37b67698a373db5b47a" dependencies = [ "arrayvec", "borsh", @@ -2283,15 +1877,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc_version" @@ -2316,9 +1904,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.10" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", "ring 0.17.8", @@ -2368,15 +1956,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "092474d1a01ea8278f69e6a358998405fae5b8b963ddaeb2b0b04a128bf1dfb0" [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "schannel" @@ -2429,11 +2017,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.2" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", "core-foundation", "core-foundation-sys", "libc", @@ -2442,9 +2030,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" dependencies = [ "core-foundation-sys", "libc", @@ -2452,35 +2040,35 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.197" +version = "1.0.201" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.201" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.61", ] [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "itoa", "ryu", @@ -2544,17 +2132,11 @@ dependencies = [ "keccak", ] -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -2576,15 +2158,15 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", "windows-sys 0.52.0", @@ -2602,12 +2184,6 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "subtle" version = "2.5.0" @@ -2627,9 +2203,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.52" +version = "2.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" +checksum = "c993ed8ccba56ae856363b1845da7266a7cb78e1d146c8a32d54b45a8b831fc9" dependencies = [ "proc-macro2", "quote", @@ -2645,7 +2221,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.61", ] [[package]] @@ -2660,20 +2236,11 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - [[package]] name = "time" -version = "0.3.34" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", @@ -2692,9 +2259,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ "num-conv", "time-core", @@ -2717,9 +2284,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.36.0" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", @@ -2752,7 +2319,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.61", ] [[package]] @@ -2784,7 +2351,7 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls 0.21.10", + "rustls 0.21.12", "tokio", ] @@ -2801,16 +2368,15 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] @@ -2825,7 +2391,7 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap 2.2.5", + "indexmap 2.2.6", "toml_datetime", "winnow", ] @@ -2850,7 +2416,7 @@ dependencies = [ "percent-encoding", "pin-project", "prost", - "rustls 0.21.10", + "rustls 0.21.12", "rustls-native-certs", "rustls-pemfile 1.0.4", "tokio", @@ -2914,7 +2480,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.61", ] [[package]] @@ -2990,9 +2556,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" [[package]] name = "vcpkg" @@ -3042,7 +2608,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.61", "wasm-bindgen-shared", ] @@ -3064,7 +2630,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.61", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3087,9 +2653,9 @@ dependencies = [ [[package]] name = "web30" -version = "1.2.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3419dff65e026307b5df735b38df61d590a0d57e8040e545d1d1f433cbd0b621" +checksum = "65fedeab1a30bd13339b7319c76c3f99b1db064858a961a0841bb107f77dfb81" dependencies = [ "awc", "clarity", @@ -3139,15 +2705,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -[[package]] -name = "winapi-util" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" -dependencies = [ - "winapi", -] - [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -3160,7 +2717,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -3178,7 +2735,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -3198,17 +2755,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.52.4", - "windows_aarch64_msvc 0.52.4", - "windows_i686_gnu 0.52.4", - "windows_i686_msvc 0.52.4", - "windows_x86_64_gnu 0.52.4", - "windows_x86_64_gnullvm 0.52.4", - "windows_x86_64_msvc 0.52.4", + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -3219,9 +2777,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" @@ -3231,9 +2789,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" @@ -3243,9 +2801,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" @@ -3255,9 +2819,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" @@ -3267,9 +2831,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" @@ -3279,9 +2843,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" @@ -3291,9 +2855,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winnow" @@ -3315,47 +2879,47 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.61", ] [[package]] name = "zstd" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bffb3309596d527cfcba7dfc6ed6052f1d39dfbd7c867aa2e865e4a449c10110" +checksum = "2d789b1514203a1120ad2429eae43a7bd32b90976a7bb8a05f7ec02fa88cc23a" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "7.0.0" +version = "7.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43747c7422e2924c11144d5229878b98180ef8b06cca4ab5af37afc8a8d8ea3e" +checksum = "1cd99b45c6bc03a018c8b8a86025678c87e55526064e38f9df301989dce7ec0a" dependencies = [ "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.9+zstd.1.5.5" +version = "2.0.10+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" dependencies = [ "cc", "pkg-config", diff --git a/gravity-info-server/Cargo.toml b/althea-info-server/Cargo.toml similarity index 51% rename from gravity-info-server/Cargo.toml rename to althea-info-server/Cargo.toml index d120208..18eb864 100644 --- a/gravity-info-server/Cargo.toml +++ b/althea-info-server/Cargo.toml @@ -1,18 +1,12 @@ [package] -name = "gravity-info-server" +name = "althea-info-server" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -ethereum_gravity = {git = "https://github.com/gravity-bridge/gravity-bridge", rev="34fde72dd63eb08d01d43fdcc1cfff86e87b3be7"} -cosmos_gravity = {git = "https://github.com/gravity-bridge/gravity-bridge", rev="34fde72dd63eb08d01d43fdcc1cfff86e87b3be7"} -gravity_utils = {git = "https://github.com/gravity-bridge/gravity-bridge", rev="34fde72dd63eb08d01d43fdcc1cfff86e87b3be7"} -relayer = {git = "https://github.com/gravity-bridge/gravity-bridge", rev="34fde72dd63eb08d01d43fdcc1cfff86e87b3be7"} -jsonrpc_server = {git = "https://github.com/gravity-bridge/gravity-bridge", rev="34fde72dd63eb08d01d43fdcc1cfff86e87b3be7"} -gravity_proto = "0.4.3" -deep_space = "2.23" +deep_space = "2.24" web30 = "1.2" clarity = "1.2" serde_derive = "1" @@ -32,7 +26,6 @@ tokio = {version="1", features=["rt-multi-thread"]} cosmos-sdk-proto-althea = "0.16" sha256 = "1" prost-types ="0.12" -rocksdb = "0.22" actix-rt = "2.5.0" serde_json = "1.0" json = "0.12.4" diff --git a/althea-info-server/src/main.rs b/althea-info-server/src/main.rs new file mode 100644 index 0000000..da5d70f --- /dev/null +++ b/althea-info-server/src/main.rs @@ -0,0 +1,119 @@ +#[macro_use] +extern crate lazy_static; + +pub mod tls; +pub mod total_suppy; + +const DEVELOPMENT: bool = cfg!(feature = "development"); +const SSL: bool = !DEVELOPMENT; +const DOMAIN: &str = if cfg!(test) || DEVELOPMENT { + "localhost" +} else { + "info.althea.link" +}; +/// The backend RPC port for the info server fucntions implemented in this repo +const INFO_SERVER_PORT: u16 = 9000; + +use crate::{ + tls::{load_certs, load_private_key}, + total_suppy::get_supply_info, +}; +use actix_cors::Cors; +use actix_web::{get, App, HttpResponse, HttpServer, Responder}; +use env_logger::Env; +use log::{error, info}; +use rustls::ServerConfig; +use total_suppy::chain_total_supply_thread; + +pub const ALTHEA_NODE_GRPC: &str = "https://rpc.althea.zone:9090"; +pub const ALTHEA_PREFIX: &str = "althea"; +pub const REQUEST_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10); + +#[get("/total_supply")] +async fn get_total_supply() -> impl Responder { + // if we have already computed supply info return it, if not return an error + match get_supply_info() { + Some(v) => HttpResponse::Ok().json(v.total_supply), + None => HttpResponse::InternalServerError() + .json("Info not yet generated, please query in 5 minutes"), + } +} + +/// If the liquid supply is lower than this value it's stale or otherwise invalid and we should +/// return an error. +pub const SUPPLY_CHECKPOINT: u128 = 500000000000000; +#[get("/total_liquid_supply")] +async fn get_total_liquid_supply() -> impl Responder { + // if we have already computed supply info return it, if not return an error + match get_supply_info() { + Some(v) => { + if v.total_liquid_supply > SUPPLY_CHECKPOINT.into() { + HttpResponse::Ok().json(v.total_liquid_supply) + } else { + error!("Invalid supply data, got total liquid supply of {:#?}", v); + HttpResponse::InternalServerError() + .json("Invalid supply data, Gravity fullnode is stale") + } + } + None => HttpResponse::InternalServerError() + .json("Info not yet generated, please query in 5 minutes"), + } +} + +#[get("/supply_info")] +async fn get_all_supply_info() -> impl Responder { + // if we have already computed supply info return it, if not return an error + match get_supply_info() { + Some(v) => { + if v.total_liquid_supply > SUPPLY_CHECKPOINT.into() { + HttpResponse::Ok().json(v) + } else { + error!("Invalid supply data, got total liquid supply of {:#?}", v); + HttpResponse::InternalServerError() + .json("Invalid supply data, Gravity fullnode is stale") + } + } + None => HttpResponse::InternalServerError() + .json("Info not yet generated, please query in 5 minutes"), + } +} + +#[actix_web::main] +async fn main() -> std::io::Result<()> { + openssl_probe::init_ssl_cert_env_vars(); + env_logger::Builder::from_env(Env::default().default_filter_or("info")).init(); + // starts a background thread for downloading transactions + chain_total_supply_thread(); + + let info_server = HttpServer::new(move || { + App::new() + .wrap( + Cors::default() + .allow_any_origin() + .allow_any_header() + .allow_any_method(), + ) + .service(get_total_supply) + .service(get_total_liquid_supply) + }); + + let info_server = if SSL { + let cert_chain = load_certs(&format!("/etc/letsencrypt/live/{}/fullchain.pem", DOMAIN)); + let keys = load_private_key(&format!("/etc/letsencrypt/live/{}/privkey.pem", DOMAIN)); + let config = ServerConfig::builder() + .with_safe_defaults() + .with_no_client_auth() + .with_single_cert(cert_chain, keys) + .unwrap(); + + info!("Binding to SSL"); + + info_server.bind_rustls(format!("{}:{}", DOMAIN, INFO_SERVER_PORT), config.clone())? + } else { + info_server.bind(format!("{}:{}", DOMAIN, INFO_SERVER_PORT))? + }; + + info_server.run().await?; + + Ok(()) +} diff --git a/gravity-info-server/src/tls.rs b/althea-info-server/src/tls.rs similarity index 100% rename from gravity-info-server/src/tls.rs rename to althea-info-server/src/tls.rs diff --git a/gravity-info-server/src/total_suppy.rs b/althea-info-server/src/total_suppy.rs similarity index 96% rename from gravity-info-server/src/total_suppy.rs rename to althea-info-server/src/total_suppy.rs index 00e686e..529f8ef 100644 --- a/gravity-info-server/src/total_suppy.rs +++ b/althea-info-server/src/total_suppy.rs @@ -4,7 +4,6 @@ //! to effectively query all the data in a reasonable amount of time and compute the result locally //! This code provides a generic way to compute the total liquid supply for a cosmos chain across all vesting types -use crate::gravity_info::{GRAVITY_NODE_GRPC, GRAVITY_PREFIX, REQUEST_TIMEOUT}; use actix_web::rt::System; use cosmos_sdk_proto_althea::cosmos::bank::v1beta1::query_client::QueryClient as BankQueryClient; use cosmos_sdk_proto_althea::cosmos::bank::v1beta1::QueryBalanceRequest; @@ -26,9 +25,11 @@ use std::thread; use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; use tonic::transport::channel::Channel; +use crate::{ALTHEA_NODE_GRPC, ALTHEA_PREFIX, REQUEST_TIMEOUT}; + // update once a day const LOOP_TIME: Duration = Duration::from_secs(86400); -pub const GRAVITY_DENOM: &str = "ugraviton"; +pub const ALTHEA_DENOM: &str = "aalthea"; #[derive(Debug, Clone, Serialize)] pub struct ChainTotalSupplyNumbers { @@ -73,8 +74,8 @@ pub fn chain_total_supply_thread() { thread::spawn(move || loop { let runner = System::new(); runner.block_on(async move { - let contact = Contact::new(GRAVITY_NODE_GRPC, REQUEST_TIMEOUT, GRAVITY_PREFIX).unwrap(); - match compute_liquid_supply(&contact, GRAVITY_DENOM.to_string()).await { + let contact = Contact::new(ALTHEA_NODE_GRPC, REQUEST_TIMEOUT, ALTHEA_PREFIX).unwrap(); + match compute_liquid_supply(&contact, ALTHEA_DENOM.to_string()).await { Ok(v) => { info!("Successfully updated supply info!"); set_supply_info(v); @@ -198,7 +199,7 @@ async fn compute_liquid_supply( // unvested tokens show up in the balance // but unvested delegated tokens do not, in the case where a user // has some vesting, some delegation, some balance, and some unclaimed rewards - assert!(user.balance > vesting_in_balance); + assert!(user.balance >= vesting_in_balance); total_liquid_supply += user.balance - vesting_in_balance; } // vesting has not started yet, in this case we subtract total vesting amount @@ -351,9 +352,9 @@ async fn batch_query_user_information( denom: String, ) -> Result, CosmosGrpcError> { trace!("Starting batch of {}", input.len()); - let mut bankrpc = BankQueryClient::connect(GRAVITY_NODE_GRPC).await?; - let mut distrpc = DistQueryClient::connect(GRAVITY_NODE_GRPC).await?; - let mut stakingrpc = StakingQueryClient::connect(GRAVITY_NODE_GRPC).await?; + let mut bankrpc = BankQueryClient::connect(ALTHEA_NODE_GRPC).await?; + let mut distrpc = DistQueryClient::connect(ALTHEA_NODE_GRPC).await?; + let mut stakingrpc = StakingQueryClient::connect(ALTHEA_NODE_GRPC).await?; let mut ret = Vec::new(); for account in input { @@ -475,8 +476,8 @@ mod tests { #[actix_web::test] async fn test_vesting_query() { - let contact = Contact::new(GRAVITY_NODE_GRPC, REQUEST_TIMEOUT, GRAVITY_PREFIX).unwrap(); - let supply = compute_liquid_supply(&contact, GRAVITY_DENOM.to_string()) + let contact = Contact::new(ALTHEA_NODE_GRPC, REQUEST_TIMEOUT, ALTHEA_PREFIX).unwrap(); + let supply = compute_liquid_supply(&contact, ALTHEA_DENOM.to_string()) .await .unwrap(); info!("Got a liquid supply of {:?}", supply); diff --git a/gravity-info-dash/src/App.tsx b/gravity-info-dash/src/App.tsx deleted file mode 100644 index 73aa099..0000000 --- a/gravity-info-dash/src/App.tsx +++ /dev/null @@ -1,441 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import 'bootstrap/dist/css/bootstrap.min.css'; -import './App.css'; -import { - Spinner, - CardBody, - CardTitle, - Card, - CardSubtitle, - Table, -} from "reactstrap"; -import { Attestation, BatchFees, BatchTransaction, ChainTotalSupplyNumbers, Erc20Metadata, EthInfo, GravityInfo, DepositWithMetadata, TransactionBatch, VolumeInfo } from './types'; -// 5 seconds -const UPDATE_TIME = 5000; - -const BACKEND_PORT = 9000; -export const SERVER_URL = - "https://" + window.location.hostname + ":" + BACKEND_PORT + "/"; - -function App() { - document.title = "Gravity Bridge Info" - const [gravityBridgeInfo, setGravityBridgeInfo] = useState(null); - const [ethBridgeInfo, setEthBridgeInfo] = useState(null); - const [supplyInfo, setSupplyInfo] = useState(null); - const [erc20Metadata, setErc20Metadata] = useState | null>(null); - const [volumeInfo, setVolumeInfo] = useState(null); - - async function getGravityInfo() { - let request_url = SERVER_URL + "gravity_bridge_info"; - const requestOptions: any = { - method: "GET", - headers: { - Accept: "application/json", - "Content-Type": "application/json", - }, - }; - - const result = await fetch(request_url, requestOptions); - const json = await result.json(); - setGravityBridgeInfo(json) - } - async function getEthInfo() { - let request_url = SERVER_URL + "eth_bridge_info"; - const requestOptions: any = { - method: "GET", - headers: { - Accept: "application/json", - "Content-Type": "application/json", - }, - }; - - const result = await fetch(request_url, requestOptions); - const json: EthInfo = await result.json(); - // reverse so these show up in reverse cronological order - json.batch_events.reverse() - json.deposit_events.reverse() - json.logic_calls.reverse() - json.valset_updates.reverse() - setEthBridgeInfo(json) - } - async function getDistributionInfo() { - let request_url = SERVER_URL + "supply_info"; - const requestOptions: any = { - method: "GET", - headers: { - Accept: "application/json", - "Content-Type": "application/json", - }, - }; - - const result = await fetch(request_url, requestOptions); - const json = await result.json(); - setSupplyInfo(json) - } - async function getErc20Metadata() { - let request_url = SERVER_URL + "erc20_metadata"; - const requestOptions: any = { - method: "GET", - headers: { - Accept: "application/json", - "Content-Type": "application/json", - }, - }; - - const result = await fetch(request_url, requestOptions); - const json = await result.json(); - setErc20Metadata(json) - } - async function getVolumeInfo() { - let request_url = SERVER_URL + "bridge_volume"; - const requestOptions: any = { - method: "GET", - headers: { - Accept: "application/json", - "Content-Type": "application/json", - }, - }; - - const result = await fetch(request_url, requestOptions); - const json = await result.json(); - setVolumeInfo(json) - } - - - useEffect(() => { - getDistributionInfo(); - getGravityInfo(); - getEthInfo(); - getErc20Metadata(); - getVolumeInfo(); - //eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - useEffect(() => { - const interval = setInterval(() => { - getDistributionInfo(); - getGravityInfo(); - getEthInfo(); - getErc20Metadata(); - getVolumeInfo(); - }, UPDATE_TIME); - return () => clearInterval(interval); - //eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - if (gravityBridgeInfo == null || typeof (gravityBridgeInfo) === "string" || ethBridgeInfo == null || supplyInfo == null || typeof (supplyInfo) === "string" || erc20Metadata == null || volumeInfo == null || typeof (volumeInfo) === "string") { - return ( -
- - Loading... - -
- ) - } - - let bridge_address = gravityBridgeInfo.params.bridge_ethereum_address; - let etherscanBase = "https://etherscan.io/address/" - let etherscanBlockBase = "https://etherscan.io/block/" - let etherscanLink = etherscanBase + bridge_address; - - return ( -
-
- - - - Transaction Queue - - These transactions are not yet in batches, a batch will be reqested when the fee amount exceeds the cost to execute on Ethereum - - - - - - - - - - { - gravityBridgeInfo.pending_tx.map((batchFees: BatchFees) => ( - - - - - )) - } - - -
- Token - - Num Transactions - - Total Fees -
- {getMetadataFromList(batchFees.token, erc20Metadata)?.symbol} - - {batchFees.tx_count} - - {amountToFraction(batchFees.token, batchFees.total_fees, erc20Metadata)} -
-
-
-
-
- - - - Batch Queue - - These transactions are in batches and waiting to be relayed to Ethereum - { - getNotExecutedBatches(gravityBridgeInfo, ethBridgeInfo).map((batch: TransactionBatch) => ( - - Batch #{batch.nonce} {getMetadataFromList(batch.token_contract, erc20Metadata)?.symbol} -
Total Fees: {amountToFraction(batch.token_contract, batch.total_fee.amount, erc20Metadata)}
- - - - - - - - - - - { - batch.transactions.map((batchTx: BatchTransaction) => ( - - - - )) - } - - -
- To - - From - - Amount / Fee -
- {batchTx.destination} - - {batchTx.sender} - - {amountToFraction(batchTx.erc20_token.contract, batchTx.erc20_token.amount, erc20Metadata)}/ - {amountToFraction(batchTx.erc20_token.contract, batchTx.erc20_fee.amount, erc20Metadata)} -
-
-
)) - } -
-
-
-
- - - - Incoming transactions - - - - - - - - - - - - - { - ethBridgeInfo.deposit_events.map((sendToCosmos: DepositWithMetadata) => ( - - - - - - - )) - } - - -
- Token - - Value - - Source - - Destination - - Status -
- {getMetadataFromList(sendToCosmos.erc20, erc20Metadata)?.symbol} - - {amountToFraction(sendToCosmos.erc20, sendToCosmos.amount, erc20Metadata)} - - {sendToCosmos.sender} - - {sendToCosmos.destination} - - {printTxStatus(sendToCosmos, gravityBridgeInfo.attestations)} -
-
-
-
-
- - - - Gravity Volume - -
Daily Volume ${(volumeInfo.daily_volume / 10 ** 6).toFixed(2)}M
-
Daily Inflow ${(volumeInfo.daily_inflow / 10 ** 6).toFixed(2)}M
-
Daily Outflow ${(volumeInfo.daily_outflow / 10 ** 6).toFixed(2)}M
-
Weekly Volume ${(volumeInfo.weekly_volume / 10 ** 6).toFixed(2)}M
-
Weekly Inflow ${(volumeInfo.weekly_inflow / 10 ** 6).toFixed(2)}M
-
Weekly Outflow ${(volumeInfo.weekly_outflow / 10 ** 6).toFixed(2)}M
-
-
-
-
- - - - Gravity Supply Info - -
Total Supply: {(supplyInfo.total_supply / 10 ** 12).toFixed(2)}M Graviton
-
Community Pool: {(supplyInfo.community_pool / 10 ** 12).toFixed(2)}M Graviton
-
Liquid (Not Vesting): {(supplyInfo.total_liquid_supply / 10 ** 12).toFixed(2)}M Graviton
-
Liquid (Not Vesting) and staked: {(supplyInfo.total_nonvesting_staked / 10 ** 12).toFixed(2)}M Graviton
-
Unclaimed staking rewards: {(supplyInfo.total_unclaimed_rewards / 10 ** 12).toFixed(2)}M Graviton
-
Unvested: {(supplyInfo.total_vesting / 10 ** 12).toFixed(2)}M Graviton
-
Unvested Staked: {(supplyInfo.total_vesting_staked / 10 ** 12).toFixed(2)}M Graviton
-
Vested: {(supplyInfo.total_vested / 10 ** 12).toFixed(2)}M Graviton
-
-
-
-
- - - - Current Gravity Parameters - -
Ethereum Contract Address: {bridge_address}
-
Bridge Active: {String(gravityBridgeInfo.params.bridge_active)}
-
Target Batch Timeout: {(gravityBridgeInfo.params.target_batch_timeout / 1000) / (60 * 60)} hours
-
-
-
-
- ); -} - -/// Inefficient utility function to lookup token metadata, should be using a map -/// of some kind -function getMetadataFromList(erc20: string, metadata: Array) { - var arrayLength = metadata.length; - for (var i = 0; i < arrayLength; i++) { - if (metadata[i].address === erc20) { - return metadata[i] - } - } - return null -} - -/// returns a readable fraction value for a given erc20 amount, if the exchange rate is populated -/// it is used to display token value / dollar value -function amountToFraction(erc20: string, amount: number, metadata: Array) { - let tokenInfo = getMetadataFromList(erc20, metadata); - if (tokenInfo == null) { - return 0 - } - let fraction = amount / 10 ** tokenInfo.decimals; - if (tokenInfo.exchange_rate == null) { - return fraction.toFixed(2); - } else { - let dollar_value = fraction * (tokenInfo.exchange_rate / 10 ** 6); - return "$" + dollar_value.toFixed(2) - } -} - -/// Takes both info structs to cross compare and display batches that have not yet been -/// executed without waiting 20 minutes for Gravity to know that a batch has been executed -/// on Ethereum -function getNotExecutedBatches(gravityBridgeInfo: GravityInfo, ethBridgeInfo: EthInfo) { - let ret = []; - var arrayLength = gravityBridgeInfo.pending_batches.length; - for (var i = 0; i < arrayLength; i++) { - if (!alreadyExecuted(gravityBridgeInfo.pending_batches[i].nonce, ethBridgeInfo)) { - ret.push(gravityBridgeInfo.pending_batches[i]) - } - } - return ret -} - -/// Checks if a batch has already executed on Ethereum but GB does not -/// know it yet by searching the eth events history -function alreadyExecuted(batch_nonce: number, ethBridgeInfo: EthInfo) { - var arrayLength = ethBridgeInfo.batch_events.length; - for (var i = 0; i < arrayLength; i++) { - if (ethBridgeInfo.batch_events[i].batch_nonce === batch_nonce) { - return true - } - } - return false -} - -/// Takes various cosmos addresses to create a proper mintscan link -function cosmosAddressToExplorerLink(input: string) { - let gravBase = "https://mintscan.io/gravity-bridge/account/" - let osmoBase = "https://mintscan.io/osmosis/account/" - let crescentBase = "https://mintscan.io/crescent/account/" - let cantoBase = "https://mintscan.io/canto/account/" - let cosmosBase = "https://mintscan.io/cosmos/account/" - let kujiBase = "https://finder.kujira.network/kaiyo-1/address/" - let mantleBase = "https://mintscan.io/mantle/account/" - if (input.startsWith("gravity")) { - return gravBase + input - } else if (input.startsWith("canto")) { - return cantoBase + input - } else if (input.startsWith("osmo")) { - return osmoBase + input - } else if (input.startsWith("cre")) { - return crescentBase + input - } else if (input.startsWith("mantle")) { - return mantleBase + input - } else if (input.startsWith("cosmos")) { - return cosmosBase + input - } else if (input.startsWith("kujira")) { - return kujiBase + input - } else { - return input - } -} - -// takes a send to Cosmos event and determines its status -function printTxStatus(event: DepositWithMetadata, events: Array) { - if (event.confirmed) { - return "Complete" - } else { - return "Pending " + event.seconds_until_confirmed + "s" - } -} - - -export default App; \ No newline at end of file diff --git a/gravity-info-dash/src/types.tsx b/gravity-info-dash/src/types.tsx deleted file mode 100644 index 833acad..0000000 --- a/gravity-info-dash/src/types.tsx +++ /dev/null @@ -1,149 +0,0 @@ -export type BatchFees = { - token: string, - total_fees: number, - tx_count: number -} - -export type Attestation = { - height: number, - observed: boolean, - votes: number -} - -export type GravityParams = { - bridge_ethereum_address: string, - average_block_time: number, - avearge_ethereum_block_time: number, - target_batch_timeout: number, - bridge_active: boolean, - ethereum_blacklist: Array, - gravity_id: string, - bridge_chain_id: number, - signed_valsets_window: number, - signed_batches_window: number, - signed_logic_calls_window: number, - unbond_slashing_valsets_window: number, - valset_reward: Coin | null -} - -export type Coin = { - denom: string, - amount: number, -} - -export type Erc20Token = { - amount: number, - contract: string -} - -export type TransactionBatch = { - nonce: number, - batch_timeout: number, - transactions: Array, - total_fee: Erc20Token - token_contract: string -} - -export type BatchTransaction = { - id: number, - sender: string, - destination: string, - erc20_token: Erc20Token, - erc20_fee: Erc20Token -} - -export type GravityInfo = { - pending_tx: Array, - pending_batches: Array - attestations: Array, - params: GravityParams -} - -export type ChainTotalSupplyNumbers = { - community_pool: number, - total_supply: number, - total_liquid_supply: number, - total_liquid_balances: number, - total_unclaimed_rewards: number, - total_nonvesting_staked: number, - total_vesting: number, - total_vesting_staked: number, - total_vested: number, -} - -export type DepositWithMetadata = { - erc20: string, - sender: string, - destination: string, - amount: number, - event_nonce: number, - block_height: number - confirmed: boolean, - blocks_until_confirmed: number, - seconds_until_confirmed: number, -} - -export type TransactionBatchExecutedEvent = { - batch_nonce: number, - block_height: number, - erc20: string, - event_nonce: number, -} - -export type ValsetUpdatedEvent = { - valset_nonce: number, - event_nonce: number, - block_height: number, - reward_amount: number, - reward_token: string | null, - members: Array - -} - -export type ValsetMember = { - power: number, - eth_address: string -} - -export type Erc20DeployedEvent = { - cosmos_denom: string, - erc20_address: string, - name: string, - symbol: string, - decimals: number, - event_nonce: number, - block_height: number, -} - -export type LogicCallExecutedEvent = { - invalidation_id: Array, - invalidation_nonce: number, - return_data: Array, - event_nonce: number, - block_height: number, -} - -export type EthInfo = { - deposit_events: Array, - batch_events: Array, - valset_updates: Array, - erc20_deploys: Array, - logic_calls: Array, - daily_volume: Number -} - -export type Erc20Metadata = { - address: string, - decimals: number, - symbol: string, - exchange_rate: number | null -} - -export type VolumeInfo = { - daily_volume: number, - daily_inflow: number, - daily_outflow: number, - weekly_volume: number, - weekly_inflow: number, - weekly_outflow: number, -} \ No newline at end of file diff --git a/gravity-info-server/src/batch_relaying.rs b/gravity-info-server/src/batch_relaying.rs deleted file mode 100644 index 3220a94..0000000 --- a/gravity-info-server/src/batch_relaying.rs +++ /dev/null @@ -1,98 +0,0 @@ -use actix_web::{HttpResponse, Responder}; -use clarity::utils::bytes_to_hex_str; -use clarity::{Address as EthAddress, Uint256}; -use cosmos_gravity::query::{ - get_gravity_params, get_latest_transaction_batches, get_transaction_batch_signatures, -}; -use deep_space::Contact; -use ethereum_gravity::message_signatures::encode_tx_batch_confirm_hashed; -use ethereum_gravity::submit_batch::encode_batch_payload; -use gravity_proto::gravity::query_client::QueryClient as GravityQueryClient; -use gravity_utils::types::TransactionBatch; -use log::error; -use relayer::find_latest_valset::find_latest_valset; -use std::time::Duration; -use web30::client::Web3; - -use crate::gravity_info::{ETH_NODE_RPC, GRAVITY_NODE_GRPC, GRAVITY_PREFIX, REQUEST_TIMEOUT}; - -pub async fn generate_raw_batch_tx(batch_nonce: u64) -> impl Responder { - let web3 = Web3::new(ETH_NODE_RPC, REQUEST_TIMEOUT); - let _contact = Contact::new(GRAVITY_NODE_GRPC, REQUEST_TIMEOUT, GRAVITY_PREFIX).unwrap(); - let mut grpc = loop { - match GravityQueryClient::connect(GRAVITY_NODE_GRPC).await { - Ok(client) => break client, - Err(e) => { - error!("Failed to connect to the GRPC server: {:?}", e); - tokio::time::sleep(Duration::from_secs(3)).await; - } - } - }; - let params = match get_gravity_params(&mut grpc).await { - Ok(p) => p, - Err(_) => return HttpResponse::InternalServerError().json("Failed to get gravity params!"), - }; - let gravity_bridge_address: EthAddress = match params.bridge_ethereum_address.parse() { - Ok(a) => a, - Err(_) => return HttpResponse::InternalServerError().json("Interanl error"), - }; - - // find the target batch and check that it's not timed out - let latest_eth_height = match web3.eth_block_number().await { - Ok(bn) => bn, - Err(_) => { - return HttpResponse::InternalServerError().json("Failed to get latest eth height") - } - }; - let latest_batches = match get_latest_transaction_batches(&mut grpc).await { - Ok(v) => v, - Err(_) => return HttpResponse::InternalServerError().json("Failed to get batches!"), - }; - let mut target_batch: Option = None; - for current_batch in latest_batches { - if current_batch.nonce == batch_nonce { - if Uint256::from(current_batch.batch_timeout) < latest_eth_height { - return HttpResponse::BadRequest().json("Batch has timed out!"); - } - target_batch = Some(current_batch); - break; - } - } - let target_batch = match target_batch { - Some(b) => b, - - None => return HttpResponse::BadRequest().json("Batch nonce not found!"), - }; - - let sigs = get_transaction_batch_signatures( - &mut grpc, - target_batch.nonce, - target_batch.token_contract, - ) - .await - .expect("Failed to get sigs for batch!"); - if sigs.is_empty() { - return HttpResponse::InternalServerError().json("Failed to get sigs for batch"); - } - - let current_valset = find_latest_valset(&mut grpc, gravity_bridge_address, &web3).await; - if current_valset.is_err() { - error!("Could not get current valset! {:?}", current_valset); - return HttpResponse::InternalServerError().json("Failed tog et sigs for batch"); - } - let current_valset = current_valset.unwrap(); - - // this checks that the signatures for the batch are actually possible to submit to the chain - let hash = encode_tx_batch_confirm_hashed(params.gravity_id.clone(), target_batch.clone()); - - if let Err(e) = current_valset.order_sigs(&hash, &sigs, true) { - error!("Current validator set is not valid to relay this batch, a validator set update must be submitted!"); - error!("{:?}", e); - return HttpResponse::InternalServerError().json("sig order not valid"); - } - - match encode_batch_payload(current_valset, &target_batch, &sigs, params.gravity_id) { - Ok(payload) => HttpResponse::Ok().json(bytes_to_hex_str(&payload)), - Err(_) => HttpResponse::InternalServerError().json("Failed to encode payload!"), - } -} diff --git a/gravity-info-server/src/gravity_info.rs b/gravity-info-server/src/gravity_info.rs deleted file mode 100644 index 3c332af..0000000 --- a/gravity-info-server/src/gravity_info.rs +++ /dev/null @@ -1,484 +0,0 @@ -//! This thread handles querying Gravity Bridge and Ethereum for information -//! and using this info to update global lazy static data in memory, this decouples requests -//! for info from the actual info gathering and makes queries dramatically more scalable. - -use actix_web::rt::System; -use clarity::{Address as EthAddress, Uint256}; -use cosmos_gravity::query::{ - get_attestations, get_gravity_params, get_latest_transaction_batches, get_pending_batch_fees, -}; -use deep_space::{Address, Coin, Contact}; -use futures::future::{join, join5, join_all}; -use futures::join; -use gravity_proto::gravity::query_client::QueryClient as GravityQueryClient; -use gravity_proto::gravity::{ - Attestation, BatchFees, Params as GravityParams, QueryDenomToErc20Request, -}; -use gravity_utils::error::GravityError; -use gravity_utils::types::{event_signatures::*, *}; -use gravity_utils::types::{SendToCosmosEvent, TransactionBatch}; -use log::{error, info, trace}; -use serde::Serialize; -use std::sync::{Arc, RwLock}; -use std::thread; -use std::time::Duration; -use tonic::transport::channel::Channel; -use web30::amm::USDC_CONTRACT_ADDRESS; -use web30::client::Web3; - -const LOOP_TIME: Duration = Duration::from_secs(30); -pub const REQUEST_TIMEOUT: Duration = Duration::from_secs(10); -pub const GRAVITY_NODE_GRPC: &str = "http://gravitychain.io:9090"; -//pub const GRAVITY_NODE_GRPC: &str = "http://chainripper-2.althea.net:9090"; -pub const GRAVITY_PREFIX: &str = "gravity"; -pub const ETH_NODE_RPC: &str = "https://eth.chandrastation.com"; -pub const FINALITY_DELAY: u128 = 100; -/// number of seconds per eth block -pub const ETH_BLOCK_TIME: u128 = 12; - -/// In memory store of gravity state used to serve rpc requests -#[derive(Debug, Default, Clone, Serialize)] -pub struct GravityInfo { - /// Pending transactions from Gravity Bridge to Ethereum - pub pending_tx: Vec, - pub pending_batches: Vec, - pub attestations: Vec, - pub params: InternalGravityParams, -} - -/// In memory store of Ethereum state used to serve rpc requests -#[derive(Debug, Default, Clone, Serialize)] -pub struct EthInfo { - pub deposit_events: Vec, - pub batch_events: Vec, - pub valset_updates: Vec, - pub erc20_deploys: Vec, - pub logic_calls: Vec, - pub latest_eth_block: Uint256, -} - -lazy_static! { - static ref GRAVITY_INFO: Arc>> = Arc::new(RwLock::new(None)); - static ref ETH_INFO: Arc>> = Arc::new(RwLock::new(None)); - static ref ERC20_METADATA: Arc>>> = - Arc::new(RwLock::new(None)); -} - -pub fn get_gravity_info() -> Option { - GRAVITY_INFO.read().unwrap().clone() -} - -fn set_gravity_info(info: GravityInfo) { - let mut lock = GRAVITY_INFO.write().unwrap(); - *lock = Some(info) -} - -pub fn get_eth_info() -> Option { - ETH_INFO.read().unwrap().clone() -} - -fn set_eth_info(info: EthInfo) { - let mut lock = ETH_INFO.write().unwrap(); - *lock = Some(info) -} - -pub fn get_erc20_metadata() -> Option> { - ERC20_METADATA.read().unwrap().clone() -} - -fn set_erc20_metadata(metadata: Vec) { - let mut lock = ERC20_METADATA.write().unwrap(); - *lock = Some(metadata) -} - -pub fn blockchain_info_thread() { - info!("Starting Gravity info watcher"); - - thread::spawn(move || loop { - let runner = System::new(); - runner.block_on(async move { - let web30 = Web3::new(ETH_NODE_RPC, REQUEST_TIMEOUT); - let contact = Contact::new(GRAVITY_NODE_GRPC, REQUEST_TIMEOUT, GRAVITY_PREFIX).unwrap(); - - let mut grpc_client = loop { - match GravityQueryClient::connect(GRAVITY_NODE_GRPC).await { - Ok(client) => break client, - Err(e) => { - error!("Failed to connect to the GRPC server: {:?}", e); - tokio::time::sleep(Duration::from_secs(3)).await; - } - } - }; - - let gravity_contract_address = match query_gravity_info(&mut grpc_client).await { - Ok(v) => { - let bridge_eth_address = v.params.bridge_ethereum_address; - set_gravity_info(v); - info!("Successfully updated Gravity info"); - bridge_eth_address - } - Err(e) => { - error!("Failed to update Gravity Info with {:?}", e); - return; - } - }; - let eth_info = query_eth_info(&web30, gravity_contract_address); - let erc20_metadata = get_all_erc20_metadata(&contact, &web30, &mut grpc_client); - let (eth_info, erc20_metadata) = join!(eth_info, erc20_metadata); - let (eth_info, erc20_metadata) = match (eth_info, erc20_metadata) { - (Ok(a), Ok(b)) => (a, b), - (_, Err(e)) => { - error!("Failed to get eth info {:?}", e); - return; - } - (Err(e), _) => { - error!("Failed to get erc20 metadata {:?}", e); - return; - } - }; - - set_eth_info(eth_info); - set_erc20_metadata(erc20_metadata); - info!("Successfully updated Gravity and ETH info"); - }); - thread::sleep(LOOP_TIME); - }); -} - -/// gets information about all tokens that have been bridged -async fn get_all_erc20_metadata( - contact: &Contact, - web30: &Web3, - grpc_client: &mut GravityQueryClient, -) -> Result, GravityError> { - let all_tokens_on_gravity = contact.query_total_supply().await?; - let mut futs = Vec::new(); - for token in all_tokens_on_gravity { - let erc20: EthAddress = if token.denom.starts_with("gravity") { - token.denom.trim_start_matches("gravity").parse().unwrap() - } else { - match grpc_client - .denom_to_erc20(QueryDenomToErc20Request { denom: token.denom }) - .await - { - Ok(v) => v.into_inner().erc20.parse().unwrap(), - Err(_) => continue, - } - }; - futs.push(get_metadata(web30, erc20)); - } - let results = join_all(futs).await; - let mut metadata = Vec::new(); - for r in results { - metadata.push(r?) - } - - Ok(metadata) -} - -async fn get_metadata(web30: &Web3, erc20: EthAddress) -> Result { - let query_sender: EthAddress = "0x388C818CA8B9251b393131C08a736A67ccB19297" - .parse() - .unwrap(); - let symbol = web30.get_erc20_symbol(erc20, query_sender); - let decimals = web30.get_erc20_decimals(erc20, query_sender); - let (symbol, decimals) = join(symbol, decimals).await; - let (symbol, decimals) = (symbol?, decimals?); - - // the token is USDC, no more querying required - if erc20 == *USDC_CONTRACT_ADDRESS { - return Ok(Erc20Metadata { - address: erc20, - symbol, - decimals, - exchange_rate: Some(10u128.pow(6).into()), - }); - } - - let downcast_decimals: u32 = decimals.to_string().parse().unwrap(); - // one of whatever this token is - let one: Uint256 = 10u128.pow(downcast_decimals).into(); - - let pricev3 = web30.get_uniswap_v3_price_with_retries( - query_sender, - erc20, - *USDC_CONTRACT_ADDRESS, - one, - None, - None, - ); - let pricev2 = - web30.get_uniswap_v2_price(query_sender, erc20, *USDC_CONTRACT_ADDRESS, one, None); - - let (pricev3, pricev2) = join(pricev3, pricev2).await; - - // the value of one unit of whatever this is in usdc - let exchange_rate = match (pricev3, pricev2) { - (Ok(r), _) => Some(r), - (_, Ok(r)) => Some(r), - (Err(_), Err(_)) => None, - }; - Ok(Erc20Metadata { - address: erc20, - symbol, - decimals, - exchange_rate, - }) -} - -#[derive(Debug, Default, Clone, Serialize)] -pub struct Erc20Metadata { - pub address: EthAddress, - pub decimals: Uint256, - pub symbol: String, - /// the amount of this token worth one DAI (one dollar) - pub exchange_rate: Option, -} - -async fn query_gravity_info( - grpc_client: &mut GravityQueryClient, -) -> Result { - // can't be easily parallelized becuase of the grpc client :( - let pending_tx = get_pending_batch_fees(grpc_client).await?.batch_fees; - let pending_batches = get_latest_transaction_batches(grpc_client).await?; - let attestations = get_attestations(grpc_client, None).await?; - let params = get_gravity_params(grpc_client).await?; - - Ok(GravityInfo { - pending_tx: pending_tx.into_iter().map(|b| b.into()).collect(), - pending_batches, - attestations: attestations.into_iter().map(|a| a.into()).collect(), - params: params.into(), - }) -} - -/// A serializable version of the batch fees struct -#[derive(Debug, Default, Clone, Serialize)] -pub struct InternalBatchFees { - pub token: EthAddress, - pub total_fees: Uint256, - pub tx_count: u64, -} - -impl From for InternalBatchFees { - fn from(b: BatchFees) -> Self { - InternalBatchFees { - token: b.token.parse().unwrap(), - total_fees: b.total_fees.parse().unwrap(), - tx_count: b.tx_count, - } - } -} - -/// A seriializable version of the Attestation struct -#[derive(Debug, Default, Clone, Serialize)] -pub struct InteralAttestation { - pub height: u64, - pub observed: bool, - pub votes: u64, -} - -impl From for InteralAttestation { - fn from(a: Attestation) -> Self { - InteralAttestation { - height: a.height, - observed: a.observed, - votes: a.votes.len() as u64, - } - } -} - -/// A drop in for SendToCosmosEvent that provies more useful metadata to the user -#[derive(Serialize, Debug, Clone, Eq, PartialEq, Hash)] -pub struct DepositWithMetadata { - pub erc20: EthAddress, - pub sender: EthAddress, - pub destination: Address, - pub amount: Uint256, - pub event_nonce: u64, - pub block_height: Uint256, - // if this deposit is not yet executed on GB this will be false - pub confirmed: bool, - pub blocks_until_confirmed: Uint256, - pub seconds_until_confirmed: Uint256, -} - -impl DepositWithMetadata { - /// Converts an event - pub fn convert( - input: SendToCosmosEvent, - current_eth_height: Uint256, - current_final_height: Uint256, - ) -> Option { - let finished = if input.block_height < current_final_height { - true - } else { - current_eth_height - input.block_height > FINALITY_DELAY.into() - }; - // height at which Gravity will see this tx - let confirm_height = input.block_height + FINALITY_DELAY.into(); - let blocks_until_confirmed: Uint256 = if finished { - 0u8.into() - } else { - confirm_height - current_eth_height - }; - - if let Some(destination) = input.validated_destination { - Some(DepositWithMetadata { - erc20: input.erc20, - sender: input.sender, - destination, - amount: input.amount, - event_nonce: input.event_nonce, - block_height: input.block_height, - confirmed: finished, - blocks_until_confirmed, - seconds_until_confirmed: blocks_until_confirmed * ETH_BLOCK_TIME.into(), - }) - } else { - None - } - } -} - -/// A serializable version of the Gravity Params -#[derive(Debug, Default, Clone, Serialize)] -pub struct InternalGravityParams { - pub bridge_ethereum_address: EthAddress, - pub average_block_time: u64, - pub average_ethereum_block_time: u64, - pub target_batch_timeout: u64, - pub bridge_active: bool, - pub ethereum_blacklist: Vec, - pub gravity_id: String, - pub bridge_chain_id: u64, - pub signed_valsets_window: u64, - pub signed_batches_window: u64, - pub signed_logic_calls_window: u64, - pub unbond_slashing_valsets_window: u64, - pub valset_reward: Option, - pub min_chain_fee_basis_points: u64, -} - -impl From for InternalGravityParams { - fn from(p: GravityParams) -> Self { - InternalGravityParams { - bridge_ethereum_address: p.bridge_ethereum_address.parse().unwrap(), - average_block_time: p.average_block_time, - average_ethereum_block_time: p.average_ethereum_block_time, - bridge_active: p.bridge_active, - target_batch_timeout: p.target_batch_timeout, - ethereum_blacklist: p - .ethereum_blacklist - .into_iter() - .map(|a| a.parse().unwrap()) - .collect(), - gravity_id: p.gravity_id, - bridge_chain_id: p.bridge_chain_id, - signed_valsets_window: p.signed_valsets_window, - signed_batches_window: p.signed_batches_window, - signed_logic_calls_window: p.signed_logic_calls_window, - unbond_slashing_valsets_window: p.unbond_slashing_valsets_window, - valset_reward: p.valset_reward.map(|c| c.into()), - min_chain_fee_basis_points: p.min_chain_fee_basis_points, - } - } -} - -async fn query_eth_info( - web3: &Web3, - gravity_contract_address: EthAddress, -) -> Result { - let latest_block = web3.eth_block_number().await?; - let latest_finalized_block = web3.eth_get_finalized_block().await?.number; - let starting_block = latest_block - 7_200u16.into(); - - let deposits = web3.check_for_events( - starting_block, - Some(latest_block), - vec![gravity_contract_address], - vec![SENT_TO_COSMOS_EVENT_SIG], - ); - let batches = web3.check_for_events( - starting_block, - Some(latest_block), - vec![gravity_contract_address], - vec![TRANSACTION_BATCH_EXECUTED_EVENT_SIG], - ); - let valsets = web3.check_for_events( - starting_block, - Some(latest_block), - vec![gravity_contract_address], - vec![VALSET_UPDATED_EVENT_SIG], - ); - let erc20_deployed = web3.check_for_events( - starting_block, - Some(latest_block), - vec![gravity_contract_address], - vec![ERC20_DEPLOYED_EVENT_SIG], - ); - let logic_call_executed = web3.check_for_events( - starting_block, - Some(latest_block), - vec![gravity_contract_address], - vec![LOGIC_CALL_EVENT_SIG], - ); - let (deposits, batches, valsets, erc20_deployed, logic_call_executed) = join5( - deposits, - batches, - valsets, - erc20_deployed, - logic_call_executed, - ) - .await; - - let (deposits, batches, valsets, erc20_deployed, logic_call_executed) = ( - deposits?, - batches?, - valsets?, - erc20_deployed?, - logic_call_executed?, - ); - - let valsets = ValsetUpdatedEvent::from_logs(&valsets)?; - trace!("parsed valsets {:?}", valsets); - let withdraws = TransactionBatchExecutedEvent::from_logs(&batches)?; - trace!("parsed batches {:?}", batches); - let deposits = SendToCosmosEvent::from_logs(&deposits)?; - trace!("parsed deposits {:?}", deposits); - let erc20_deploys = Erc20DeployedEvent::from_logs(&erc20_deployed)?; - trace!("parsed erc20 deploys {:?}", erc20_deploys); - let logic_calls = LogicCallExecutedEvent::from_logs(&logic_call_executed)?; - trace!("logic call executions {:?}", logic_calls); - - let mut deposit_events = Vec::new(); - for d in deposits { - let d = DepositWithMetadata::convert(d, latest_block, latest_finalized_block); - if let Some(d) = d { - deposit_events.push(d); - } - } - - Ok(EthInfo { - deposit_events, - batch_events: withdraws, - valset_updates: valsets, - erc20_deploys, - logic_calls, - latest_eth_block: latest_block, - }) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[actix_web::test] - async fn test_gravity_info() { - env_logger::init(); - let mut grpc_client = GravityQueryClient::connect(GRAVITY_NODE_GRPC) - .await - .unwrap(); - let _info = query_gravity_info(&mut grpc_client).await.unwrap(); - } -} diff --git a/gravity-info-server/src/main.rs b/gravity-info-server/src/main.rs deleted file mode 100644 index f7803ed..0000000 --- a/gravity-info-server/src/main.rs +++ /dev/null @@ -1,233 +0,0 @@ -#[macro_use] -extern crate lazy_static; - -pub mod batch_relaying; -pub mod gravity_info; -pub mod tls; -pub mod total_suppy; -pub mod transactions; -pub mod volume; - -const DEVELOPMENT: bool = cfg!(feature = "development"); -const SSL: bool = !DEVELOPMENT; -const DOMAIN: &str = if cfg!(test) || DEVELOPMENT { - "localhost" -} else { - "info.gravitychain.io" -}; -/// The backend RPC port for the info server fucntions implemented in this repo -const INFO_SERVER_PORT: u16 = 9000; -/// Provides the eip-712 metamask rpc for Gravity Bridge -const METAMASK_RPC_PORT: u16 = 8545; - -use crate::batch_relaying::generate_raw_batch_tx; -use crate::gravity_info::get_erc20_metadata; -use crate::total_suppy::get_supply_info; - -use crate::volume::get_volume_info; -use crate::{gravity_info::get_gravity_info, tls::*}; -use actix_cors::Cors; -use actix_web::{get, web, App, HttpResponse, HttpServer, Responder}; - -use env_logger::Env; -use futures::future::join; -use gravity_info::{blockchain_info_thread, get_eth_info}; -use jsonrpc_server::server::request_dispatcher; -use log::{error, info}; -use rocksdb::Options; -use rocksdb::DB; -use rustls::ServerConfig; - -use std::sync::Arc; -use total_suppy::chain_total_supply_thread; -use transactions::database::transaction_info_thread; -use volume::bridge_volume_thread; - -/// This is a helper api endpoint which generates an unsigned tx for a transaction batch sent from a given address -/// and returns it to the caller. -#[get("/batch_tx/{batch_nonce}")] -async fn generate_batch_tx(data: web::Path<(u64,)>) -> impl Responder { - let nonce = data.into_inner().0; - generate_raw_batch_tx(nonce).await -} - -#[get("/total_supply")] -async fn get_total_supply() -> impl Responder { - // if we have already computed supply info return it, if not return an error - match get_supply_info() { - Some(v) => HttpResponse::Ok().json(v.total_supply), - None => HttpResponse::InternalServerError() - .json("Info not yet generated, please query in 5 minutes"), - } -} - -/// If the liquid supply is lower than this value it's stale or otherwise invalid and we should -/// return an error. -pub const SUPPLY_CHECKPOINT: u128 = 500000000000000; -#[get("/total_liquid_supply")] -async fn get_total_liquid_supply() -> impl Responder { - // if we have already computed supply info return it, if not return an error - match get_supply_info() { - Some(v) => { - if v.total_liquid_supply > SUPPLY_CHECKPOINT.into() { - HttpResponse::Ok().json(v.total_liquid_supply) - } else { - error!("Invalid supply data, got total liquid supply of {:#?}", v); - HttpResponse::InternalServerError() - .json("Invalid supply data, Gravity fullnode is stale") - } - } - None => HttpResponse::InternalServerError() - .json("Info not yet generated, please query in 5 minutes"), - } -} - -#[get("/supply_info")] -async fn get_all_supply_info() -> impl Responder { - // if we have already computed supply info return it, if not return an error - match get_supply_info() { - Some(v) => { - if v.total_liquid_supply > SUPPLY_CHECKPOINT.into() { - HttpResponse::Ok().json(v) - } else { - error!("Invalid supply data, got total liquid supply of {:#?}", v); - HttpResponse::InternalServerError() - .json("Invalid supply data, Gravity fullnode is stale") - } - } - None => HttpResponse::InternalServerError() - .json("Info not yet generated, please query in 5 minutes"), - } -} - -#[get("/eth_bridge_info")] -async fn get_eth_bridge_info() -> impl Responder { - // if we have already computed supply info return it, if not return an error - match get_eth_info() { - Some(v) => HttpResponse::Ok().json(v), - None => HttpResponse::InternalServerError() - .json("Info not yet generated, please query in 5 minutes"), - } -} - -#[get("/gravity_bridge_info")] -async fn get_gravity_bridge_info() -> impl Responder { - // if we have already computed supply info return it, if not return an error - match get_gravity_info() { - Some(v) => HttpResponse::Ok().json(v), - None => HttpResponse::InternalServerError() - .json("Info not yet generated, please query in 5 minutes"), - } -} - -#[get("/erc20_metadata")] -async fn erc20_metadata() -> impl Responder { - // if we have already computed supply info return it, if not return an error - match get_erc20_metadata() { - Some(v) => HttpResponse::Ok().json(v), - None => HttpResponse::InternalServerError() - .json("Info not yet generated, please query in 5 minutes"), - } -} - -#[get("/bridge_volume")] -async fn get_bridge_volume() -> impl Responder { - // if we have already computed volume info return it, if not return an error - match get_volume_info() { - Some(v) => HttpResponse::Ok().json(v), - None => HttpResponse::InternalServerError() - .json("Info not yet generated, please query in 20 minutes"), - } -} - -#[get("/transactions/send_to_eth")] -async fn get_all_msg_send_to_eth_transactions(db: web::Data>) -> impl Responder { - transactions::endpoints::get_all_msg_send_to_eth_transactions(db).await -} - -#[get("/transactions/ibc_transfer")] -async fn get_all_msg_ibc_transfer_transactions(db: web::Data>) -> impl Responder { - transactions::endpoints::get_all_msg_ibc_transfer_transactions(db).await -} - -#[get("/transactions/send_to_eth/time")] -async fn get_send_to_eth_transaction_totals(db: web::Data>) -> impl Responder { - transactions::endpoints::get_send_to_eth_transaction_totals(db).await -} - -#[actix_web::main] -async fn main() -> std::io::Result<()> { - openssl_probe::init_ssl_cert_env_vars(); - env_logger::Builder::from_env(Env::default().default_filter_or("info")).init(); - // starts a background thread for downloading transactions - let mut db_options = Options::default(); - db_options.create_if_missing(true); - let db = Arc::new(DB::open(&db_options, "transactions").expect("Failed to open database")); - let api_db = web::Data::new(db.clone()); - transaction_info_thread(db.clone()); - // starts background thread for gathering into - blockchain_info_thread(); - // starts a background thread for generating the total supply numbers - chain_total_supply_thread(); - // starts a background thread for generating volume numbers - bridge_volume_thread(); - - let info_server = HttpServer::new(move || { - App::new() - .wrap( - Cors::default() - .allow_any_origin() - .allow_any_header() - .allow_any_method(), - ) - .service(get_total_supply) - .service(get_total_liquid_supply) - .service(get_all_supply_info) - .service(get_eth_bridge_info) - .service(get_gravity_bridge_info) - .service(erc20_metadata) - .service(get_bridge_volume) - .app_data(api_db.clone()) - .service(get_all_msg_send_to_eth_transactions) - .service(get_all_msg_ibc_transfer_transactions) - .service(get_send_to_eth_transaction_totals) - .service(generate_batch_tx) - }); - - let metamask_server = HttpServer::new(move || { - App::new() - .wrap( - Cors::default() - .allow_any_origin() - .allow_any_header() - .allow_any_method(), - ) - .service(request_dispatcher) - }); - - let (info_server, metamask_server) = if SSL { - let cert_chain = load_certs(&format!("/etc/letsencrypt/live/{}/fullchain.pem", DOMAIN)); - let keys = load_private_key(&format!("/etc/letsencrypt/live/{}/privkey.pem", DOMAIN)); - let config = ServerConfig::builder() - .with_safe_defaults() - .with_no_client_auth() - .with_single_cert(cert_chain, keys) - .unwrap(); - - info!("Binding to SSL"); - let a = - info_server.bind_rustls(format!("{}:{}", DOMAIN, INFO_SERVER_PORT), config.clone())?; - let b = metamask_server.bind_rustls(format!("{}:{}", DOMAIN, METAMASK_RPC_PORT), config)?; - (a, b) - } else { - let a = info_server.bind(format!("{}:{}", DOMAIN, INFO_SERVER_PORT))?; - let b = metamask_server.bind(format!("{}:{}", DOMAIN, METAMASK_RPC_PORT))?; - (a, b) - }; - - let (a, b) = join(info_server.run(), metamask_server.run()).await; - a?; - b?; - - Ok(()) -} diff --git a/gravity-info-server/src/transactions/database.rs b/gravity-info-server/src/transactions/database.rs deleted file mode 100644 index ec11d5e..0000000 --- a/gravity-info-server/src/transactions/database.rs +++ /dev/null @@ -1,515 +0,0 @@ -use crate::gravity_info::{GRAVITY_NODE_GRPC, GRAVITY_PREFIX, REQUEST_TIMEOUT}; -use actix_rt::System; -use cosmos_sdk_proto_althea::{ - cosmos::tx::v1beta1::{TxBody, TxRaw}, - ibc::{applications::transfer::v1::MsgTransfer, core::client::v1::Height}, -}; -use deep_space::{client::Contact, utils::decode_any}; -use futures::future::join_all; -use gravity_proto::gravity::MsgSendToEth; -use lazy_static::lazy_static; -use log::{error, info}; -use rocksdb::DB; -use serde::{Deserialize, Serialize}; -use std::sync::atomic::{AtomicUsize, Ordering}; -use std::time::Duration; -use std::{ - sync::{Arc, RwLock}, - thread, - time::Instant, -}; -use tokio::time::sleep; - -lazy_static! { - static ref COUNTER: Arc> = Arc::new(RwLock::new(Counters { - blocks: 0, - transactions: 0, - msgs: 0, - ibc_msgs: 0, - send_eth_msgs: 0 - })); -} - -pub struct Counters { - blocks: u64, - transactions: u64, - msgs: u64, - ibc_msgs: u64, - send_eth_msgs: u64, -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct CustomMsgSendToEth { - sender: String, - eth_dest: String, - pub amount: Vec, - pub bridge_fee: Vec, - pub chain_fee: Vec, -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct CustomMsgTransfer { - source_port: String, - source_channel: String, - token: Vec, - sender: String, - receiver: String, - timeout_height: Option, - timeout_timestamp: u64, -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct CustomHeight { - pub revision_number: u64, - pub revision_height: u64, -} - -impl From<&Height> for CustomHeight { - fn from(height: &Height) -> Self { - CustomHeight { - revision_number: height.revision_number, - revision_height: height.revision_height, - } - } -} - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct CustomCoin { - pub denom: String, - pub amount: String, -} - -#[derive(Serialize)] -pub struct ApiResponse { - pub tx_hash: String, - pub data: serde_json::Value, -} - -impl From<&MsgSendToEth> for CustomMsgSendToEth { - fn from(msg: &MsgSendToEth) -> Self { - CustomMsgSendToEth { - sender: msg.sender.clone(), - eth_dest: msg.eth_dest.clone(), - amount: msg - .amount - .as_ref() - .map(|coin| CustomCoin { - denom: coin.denom.clone(), - amount: coin.amount.clone(), - }) - .into_iter() - .collect(), - bridge_fee: msg - .bridge_fee - .as_ref() - .map(|coin| CustomCoin { - denom: coin.denom.clone(), - amount: coin.amount.clone(), - }) - .into_iter() - .collect(), - chain_fee: msg - .chain_fee - .as_ref() - .map(|coin| CustomCoin { - denom: coin.denom.clone(), - amount: coin.amount.clone(), - }) - .into_iter() - .collect(), - } - } -} - -impl From<&MsgTransfer> for CustomMsgTransfer { - fn from(msg: &MsgTransfer) -> Self { - CustomMsgTransfer { - source_port: msg.source_port.clone(), - source_channel: msg.source_channel.clone(), - token: msg - .token - .as_ref() - .map(|coin| CustomCoin { - denom: coin.denom.clone(), - amount: coin.amount.clone(), - }) - .into_iter() - .collect(), - sender: msg.sender.clone(), - receiver: msg.receiver.clone(), - timeout_height: msg.timeout_height.as_ref().map(CustomHeight::from), - timeout_timestamp: msg.timeout_timestamp, - } - } -} - -const MAX_RETRIES: usize = 5; - -/// finds earliest available block using binary search, keep in mind this cosmos -/// node will not have history from chain halt upgrades and could be state synced -/// and missing history before the state sync -/// Iterative implementation due to the limitations of async recursion in rust. -async fn get_earliest_block(contact: &Contact, mut start: u64, mut end: u64) -> u64 { - while start <= end { - let mid = start + (end - start) / 2; - let mid_block = contact.get_block(mid).await; - if let Ok(Some(_)) = mid_block { - end = mid - 1; - } else { - start = mid + 1; - } - } - // off by one error correction fix bounds logic up top - start + 1 -} - -// Loads sendToEth & MsgTransfer messages from grpc endpoint & downlaods to DB -async fn search(contact: &Contact, start: u64, end: u64, db: &DB) { - let mut current_start = start; - let retries = AtomicUsize::new(0); - - loop { - let blocks_result = contact.get_block_range(current_start, end).await; - - let blocks = match blocks_result { - Ok(result) => { - retries.store(0, Ordering::Relaxed); - result - } - Err(e) => { - let current_retries = retries.fetch_add(1, Ordering::Relaxed); - if current_retries >= MAX_RETRIES { - error!("Error getting block range: {:?}, exceeded max retries", e); - break; - } else { - error!("Error getting block range: {:?}, retrying", e); - tokio::time::sleep(Duration::from_secs(1)).await; - continue; - } - } - }; - - if blocks.is_empty() { - break; - } - - // gets the last block that was successfully fetched to be referenced - // in case of grpc error - let last_block_height = blocks - .last() - .unwrap() - .as_ref() - .unwrap() - .header - .as_ref() - .unwrap() - .height; - - // counters for transactions, messages, blocks & tx types - let mut tx_counter = 0; - let mut msg_counter = 0; - let mut ibc_transfer_counter = 0; - let mut send_eth_counter = 0; - let blocks_len = blocks.len() as u64; - - for block in blocks.into_iter() { - let block = block.unwrap(); - // Get the block number - let block_number = block.header.as_ref().unwrap().height; - - // tx fetching - for tx in block.data.unwrap().txs { - let raw_tx_any = prost_types::Any { - type_url: "/cosmos.tx.v1beta1.TxRaw".to_string(), - value: tx, - }; - let tx_raw: TxRaw = decode_any(raw_tx_any.clone()).unwrap(); - let value_ref: &[u8] = raw_tx_any.value.as_ref(); - let tx_hash = sha256::digest(value_ref).to_uppercase(); - let body_any = prost_types::Any { - type_url: "/cosmos.tx.v1beta1.TxBody".to_string(), - value: tx_raw.body_bytes, - }; - let tx_body: TxBody = decode_any(body_any).unwrap(); - - let mut has_msg_send_to_eth = false; - let mut has_msg_ibc_transfer = false; - - // tx sorting - for message in tx_body.messages { - if message.type_url == "/gravity.v1.MsgSendToEth" { - has_msg_send_to_eth = true; - msg_counter += 1; - - let msg_send_to_eth_any = prost_types::Any { - type_url: "/gravity.v1.MsgSendToEth".to_string(), - value: message.value, - }; - let msg_send_to_eth: Result = - decode_any(msg_send_to_eth_any); - - if let Ok(msg_send_to_eth) = msg_send_to_eth { - let custom_msg_send_to_eth = CustomMsgSendToEth::from(&msg_send_to_eth); - let timestamp = block - .header - .as_ref() - .unwrap() - .time - .as_ref() - .unwrap() - .seconds; - let key = format!( - "{:012}:msgSendToEth:{}:{}", - block_number, timestamp, tx_hash - ); - save_msg_send_to_eth(db, &key, &custom_msg_send_to_eth); - } - } else if message.type_url == "/ibc.applications.transfer.v1.MsgTransfer" { - has_msg_ibc_transfer = true; - msg_counter += 1; - - let msg_ibc_transfer_any = prost_types::Any { - type_url: "/ibc.applications.transfer.v1.MsgTransfer".to_string(), - value: message.value, - }; - let msg_ibc_transfer: Result = - decode_any(msg_ibc_transfer_any); - - if let Ok(msg_ibc_transfer) = msg_ibc_transfer { - let custom_ibc_transfer = CustomMsgTransfer::from(&msg_ibc_transfer); - let timestamp = block - .header - .as_ref() - .unwrap() - .time - .as_ref() - .unwrap() - .seconds; - let key = format!( - "{:012}:msgIbcTransfer:{}:{}", - block_number, timestamp, tx_hash - ); - save_msg_ibc_transfer(db, &key, &custom_ibc_transfer); - } - } - } - - if has_msg_send_to_eth { - tx_counter += 1; - send_eth_counter += 1; - } - if has_msg_ibc_transfer { - tx_counter += 1; - ibc_transfer_counter += 1; - } - } - current_start = (last_block_height as u64) + 1; - if current_start > end { - break; - } - } - let mut c = COUNTER.write().unwrap(); - c.blocks += blocks_len; - c.transactions += tx_counter; - c.msgs += msg_counter; - c.ibc_msgs += ibc_transfer_counter; - c.send_eth_msgs += send_eth_counter; - } -} - -pub fn transaction_info_thread(db: Arc) { - info!("Starting transaction info thread"); - - thread::spawn(move || loop { - let runner = System::new(); - runner.block_on(async { - match transactions(&db).await { - Ok(_) => (), - Err(e) => { - error!("Error downloading transactions: {:?}", e); - let mut retry_interval = Duration::from_secs(1); - loop { - info!("Retrying block download"); - sleep(retry_interval).await; - match transactions(&db).await { - Ok(_) => break, - Err(e) => { - error!("Error in transaction download retry: {:?}", e); - retry_interval = - if let Some(new_interval) = retry_interval.checked_mul(2) { - new_interval - } else { - retry_interval - }; - } - } - } - } - } - tokio::time::sleep(Duration::from_secs(24 * 60 * 60)).await; // Sleep for 24 hours - }); - }); -} - -/// creates batches of transactions found and sorted using the search function -/// then writes them to the db -pub async fn transactions(db: &DB) -> Result<(), Box> { - info!("Started downloading & parsing transactions"); - let contact: Contact = Contact::new(GRAVITY_NODE_GRPC, REQUEST_TIMEOUT, GRAVITY_PREFIX)?; - - let mut retries = 0; - let status = loop { - let result = contact.get_chain_status().await; - - match result { - Ok(chain_status) => { - break chain_status; - } - Err(e) => { - retries += 1; - if retries >= MAX_RETRIES { - error!("Failed to get chain status, grpc error: {:?}", e); - return Err(Box::new(e)); - } else { - error!("Failed to get chain status, grpc error: {:?}, retrying", e); - tokio::time::sleep(Duration::from_secs(1)).await; - } - } - } - }; - - // get the latest block this node has - let mut current_status = status; - let latest_block; - loop { - match current_status { - deep_space::client::ChainStatus::Moving { block_height } => { - latest_block = Some(block_height); - break; - } - _ => match contact.get_chain_status().await { - Ok(chain_status) => { - if let deep_space::client::ChainStatus::Moving { block_height } = chain_status { - latest_block = Some(block_height); - break; - } - current_status = chain_status; - } - Err(e) => { - retries += 1; - if retries >= MAX_RETRIES { - error!("Failed to get chain status: {:?}", e); - return Err(Box::new(e)); - } else { - error!("Failed to get chain status: {:?}, retrying", e); - tokio::time::sleep(Duration::from_secs(1)).await; - } - } - }, - } - } - - let latest_block = latest_block.expect("Node is not synced or not running"); - - // now we find the earliest block this node has via binary search, we could just read it from - // the error message you get when requesting an earlier block, but this was more fun - let earliest_block = get_earliest_block(&contact, 0, latest_block).await; - - let earliest_block = match load_last_download_block(db) { - Some(block) => block, - None => earliest_block, - }; - - info!( - "This node has {} blocks to download, downloading to database", - latest_block - earliest_block - ); - let start = Instant::now(); - - // how many blocks to search per future - const BATCH_SIZE: u64 = 500; - // how many futures to execute at once - const EXECUTE_SIZE: usize = 10; - let mut pos = earliest_block; - let mut futures = Vec::new(); - while pos < latest_block { - let start = pos; - let end = if latest_block - pos > BATCH_SIZE { - pos += BATCH_SIZE; - pos - } else { - pos = latest_block; - latest_block - }; - let fut = search(&contact, start, end, db); - futures.push(fut); - } - - let futures = futures.into_iter(); - - let mut buf = Vec::new(); - - for fut in futures { - if buf.len() < EXECUTE_SIZE { - buf.push(fut); - } else { - let _ = join_all(buf).await; - info!( - "Completed batch of {} blocks", - BATCH_SIZE * EXECUTE_SIZE as u64 - ); - buf = Vec::new(); - } - } - let _ = join_all(buf).await; - - let counter = COUNTER.read().unwrap(); - info!( - "Successfully downloaded {} blocks and {} tx containing {} send_to_eth msgs and {} ibc_transfer msgs in {} seconds", - counter.blocks, - counter.transactions, - counter.send_eth_msgs, - counter.ibc_msgs, - start.elapsed().as_secs() - ); - save_last_download_block(db, latest_block); - Ok(()) -} - -//saves serialized transactions to database -pub fn save_msg_send_to_eth(db: &DB, key: &str, data: &CustomMsgSendToEth) { - let data_json = serde_json::to_string(data).unwrap(); - db.put(key.as_bytes(), data_json.as_bytes()).unwrap(); -} - -pub fn save_msg_ibc_transfer(db: &DB, key: &str, data: &CustomMsgTransfer) { - let data_json = serde_json::to_string(data).unwrap(); - db.put(key.as_bytes(), data_json.as_bytes()).unwrap(); -} - -// Load & deseralize transactions -pub fn load_msg_send_to_eth(db: &DB, key: &str) -> Option { - let res = db.get(key.as_bytes()).unwrap(); - res.map(|bytes| serde_json::from_slice::(&bytes).unwrap()) -} - -pub fn load_msg_ibc_transfer(db: &DB, key: &str) -> Option { - let res = db.get(key.as_bytes()).unwrap(); - res.map(|bytes| serde_json::from_slice::(&bytes).unwrap()) -} - -// timestamp function using downloaded blocks as a source of truth -const LAST_DOWNLOAD_BLOCK_KEY: &str = "last_download_block"; - -fn save_last_download_block(db: &DB, timestamp: u64) { - db.put( - LAST_DOWNLOAD_BLOCK_KEY.as_bytes(), - timestamp.to_string().as_bytes(), - ) - .unwrap(); -} - -fn load_last_download_block(db: &DB) -> Option { - let res = db.get(LAST_DOWNLOAD_BLOCK_KEY.as_bytes()).unwrap(); - res.map(|bytes| String::from_utf8_lossy(&bytes).parse::().unwrap()) -} diff --git a/gravity-info-server/src/transactions/endpoints.rs b/gravity-info-server/src/transactions/endpoints.rs deleted file mode 100644 index a2a619c..0000000 --- a/gravity-info-server/src/transactions/endpoints.rs +++ /dev/null @@ -1,342 +0,0 @@ -use crate::transactions::database::CustomCoin; -use crate::transactions::database::{ApiResponse, CustomMsgSendToEth, CustomMsgTransfer}; - -use actix_web::Responder; -use actix_web::{web, HttpResponse}; -use chrono::{DateTime, Datelike, Local, NaiveDateTime, Utc}; - -use log::error; - -use rocksdb::DB; - -use serde::Serialize; -use std::collections::HashMap; -use std::sync::Arc; - -#[derive(Debug, Serialize)] -struct TimeFrameData { - time_frames: Vec, -} - -#[derive(Debug, Serialize)] -struct TimeFrame { - period: String, - amount_totals: HashMap, - bridge_fee_totals: HashMap, - chain_fee_totals: HashMap, -} - -#[derive(Serialize)] -struct BlockTransactions { - block_number: u64, - transactions: Vec, - formatted_date: String, -} - -type BlockData = (String, Vec); - -fn process_fee(fee: Vec, totals: &HashMap) -> HashMap { - let mut new_totals = totals.clone(); - for custom_coin in fee { - let decimal_value = custom_coin.amount.parse::().unwrap(); - let denom = custom_coin.denom.clone(); - *new_totals.entry(denom).or_default() += decimal_value; - } - new_totals -} - -pub async fn get_all_msg_send_to_eth_transactions(db: web::Data>) -> impl Responder { - let mut response_data: HashMap = HashMap::new(); - - let iterator = db.iterator(rocksdb::IteratorMode::Start); - - for item in iterator { - match item { - Ok((key, value)) => { - let key_str = String::from_utf8_lossy(&key); - let key_parts: Vec<&str> = key_str.split(':').collect(); - if key_parts.len() == 4 && key_parts[1] == "msgSendToEth" { - let msg_send_to_eth: CustomMsgSendToEth = - serde_json::from_slice(&value).unwrap(); - let block_number = key_parts[0].parse::().unwrap(); - - let timestamp = key_parts[2].parse::().unwrap(); - - // Convert timestamp to Option - let naive_opt = NaiveDateTime::from_timestamp_opt(timestamp, 0); - - let mut _datetime_utc: Option> = None; - - if let Some(naive_datetime) = naive_opt { - // Convert Option to DateTime - _datetime_utc = - Some(DateTime::from_naive_utc_and_offset(naive_datetime, Utc)); - } else { - error!("Invalid timestamp: {}", timestamp); - continue; // skip this iteration if timestamp is invalid - } - - let datetime_utc = _datetime_utc.unwrap(); // we can safely unwrap because of the `continue` above - - let datetime_local: DateTime = datetime_utc.into(); - - // Extract month, day, and year - let month = datetime_local.month(); - let day = datetime_local.day(); - let year = datetime_local.year(); - - // Format the date string - let formatted_date = format!("{:02}-{:02}-{}", month, day, year); - let api_response = ApiResponse { - tx_hash: key_parts[3].to_string(), - data: serde_json::to_value(&msg_send_to_eth).unwrap(), - }; - - response_data - .entry(block_number) - .or_insert((formatted_date, Vec::new())) - .1 - .push(api_response); - } - } - Err(err) => { - error!("RocksDB iterator error: {}", err); - } - } - } - - // Converting the HashMap to a Vec and sorting it by block number - let mut response_data: Vec<_> = response_data.into_iter().collect(); - response_data.sort_by(|a, b| a.0.cmp(&b.0)); - - // Convert Vec of tuples into Vec of BlockTransactions - let response_data: Vec<_> = response_data - .into_iter() - .map( - |(block_number, (formatted_date, transactions))| BlockTransactions { - block_number, - formatted_date, - transactions, - }, - ) - .collect(); - - HttpResponse::Ok().json(response_data) -} - -pub async fn get_all_msg_ibc_transfer_transactions(db: web::Data>) -> impl Responder { - let mut response_data: HashMap = HashMap::new(); - - let iterator = db.iterator(rocksdb::IteratorMode::Start); - - for item in iterator { - match item { - Ok((key, value)) => { - let key_str = String::from_utf8_lossy(&key); - let key_parts: Vec<&str> = key_str.split(':').collect(); - if key_parts.len() == 4 && key_parts[1] == "msgIbcTransfer" { - let msg_ibc_transfer: CustomMsgTransfer = - serde_json::from_slice(&value).unwrap(); - let block_number = key_parts[0].parse::().unwrap(); - - let timestamp = key_parts[2].parse::().unwrap(); - - // Convert timestamp to Option - let naive_opt = NaiveDateTime::from_timestamp_opt(timestamp, 0); - - let mut _datetime_utc: Option> = None; - - if let Some(naive_datetime) = naive_opt { - // Convert Option to DateTime - _datetime_utc = Some(DateTime::::from_naive_utc_and_offset( - naive_datetime, - Utc, - )); - } else { - error!("Invalid timestamp: {}", timestamp); - continue; // skip this iteration if timestamp is invalid - } - - let datetime_utc = _datetime_utc.unwrap(); // we can safely unwrap because of the `continue` above - - let datetime_local: DateTime = datetime_utc.into(); - - // Extract month, day, and year - let month = datetime_local.month(); - let day = datetime_local.day(); - let year = datetime_local.year(); - - // Format the date string - let formatted_date = format!("{:02}-{:02}-{}", month, day, year); - let api_response = ApiResponse { - tx_hash: key_parts[3].to_string(), - data: serde_json::to_value(&msg_ibc_transfer).unwrap(), - }; - - response_data - .entry(block_number) - .or_insert((formatted_date, Vec::new())) - .1 - .push(api_response); - } - } - Err(err) => { - error!("RocksDB iterator error: {}", err); - } - } - } - - // Converting the HashMap to a Vec and sorting it by block number - let mut response_data: Vec<_> = response_data.into_iter().collect(); - response_data.sort_by(|a, b| a.0.cmp(&b.0)); - - // Convert Vec of tuples into Vec of BlockTransactions - let response_data: Vec<_> = response_data - .into_iter() - .map( - |(block_number, (formatted_date, transactions))| BlockTransactions { - block_number, - formatted_date, - transactions, - }, - ) - .collect(); - - HttpResponse::Ok().json(response_data) -} - -pub async fn get_send_to_eth_transaction_totals(db: web::Data>) -> impl Responder { - // Define the time frame duration in seconds - const ONE_DAY: u64 = 24 * 60 * 60; - const SEVEN_DAYS: u64 = 7 * ONE_DAY; - const THIRTY_DAYS: u64 = 30 * ONE_DAY; - const ONE_YEAR: u64 = 365 * ONE_DAY; - - let mut amount_totals_1day: HashMap = HashMap::new(); - let mut bridge_fee_totals_1day: HashMap = HashMap::new(); - let mut chain_fee_totals_1day: HashMap = HashMap::new(); - - let mut amount_totals_7days: HashMap = HashMap::new(); - let mut bridge_fee_totals_7days: HashMap = HashMap::new(); - let mut chain_fee_totals_7days: HashMap = HashMap::new(); - - let mut amount_totals_30days: HashMap = HashMap::new(); - let mut bridge_fee_totals_30days: HashMap = HashMap::new(); - let mut chain_fee_totals_30days: HashMap = HashMap::new(); - - let mut amount_totals_1year: HashMap = HashMap::new(); - let mut bridge_fee_totals_1year: HashMap = HashMap::new(); - let mut chain_fee_totals_1year: HashMap = HashMap::new(); - - let mut amount_totals_alltime: HashMap = HashMap::new(); - let mut bridge_fee_totals_alltime: HashMap = HashMap::new(); - let mut chain_fee_totals_alltime: HashMap = HashMap::new(); - - let iterator = db.iterator(rocksdb::IteratorMode::Start); - - for item in iterator { - match item { - Ok((key, value)) => { - let key_str = String::from_utf8_lossy(&key); - let key_parts: Vec<&str> = key_str.split(':').collect(); - if key_parts.len() == 4 && key_parts[1] == "msgSendToEth" { - let msg_send_to_eth: CustomMsgSendToEth = - serde_json::from_slice(&value).unwrap(); - let timestamp = key_parts[2].parse::().unwrap(); - - let amount = msg_send_to_eth.amount.clone(); - let bridge_fee = msg_send_to_eth.bridge_fee.clone(); - let chain_fee = msg_send_to_eth.chain_fee.clone(); - - amount_totals_alltime = process_fee(amount.clone(), &amount_totals_alltime); - bridge_fee_totals_alltime = - process_fee(bridge_fee.clone(), &bridge_fee_totals_alltime); - chain_fee_totals_alltime = - process_fee(chain_fee.clone(), &chain_fee_totals_alltime); - - // process data - if timestamp - >= (Utc::now() - chrono::Duration::seconds(ONE_DAY as i64)).timestamp() - { - // 1-day time frame - amount_totals_1day = process_fee(amount.clone(), &amount_totals_1day); - bridge_fee_totals_1day = - process_fee(bridge_fee.clone(), &bridge_fee_totals_1day); - chain_fee_totals_1day = - process_fee(chain_fee.clone(), &chain_fee_totals_1day); - } - if timestamp - >= (Utc::now() - chrono::Duration::seconds(SEVEN_DAYS as i64)).timestamp() - { - // 7-day time frame - amount_totals_7days = process_fee(amount.clone(), &amount_totals_7days); - bridge_fee_totals_7days = - process_fee(bridge_fee.clone(), &bridge_fee_totals_7days); - chain_fee_totals_7days = - process_fee(chain_fee.clone(), &chain_fee_totals_7days); - } - if timestamp - >= (Utc::now() - chrono::Duration::seconds(THIRTY_DAYS as i64)).timestamp() - { - // 30-day time frame - amount_totals_30days = process_fee(amount.clone(), &amount_totals_30days); - bridge_fee_totals_30days = - process_fee(bridge_fee.clone(), &bridge_fee_totals_30days); - chain_fee_totals_30days = - process_fee(chain_fee.clone(), &chain_fee_totals_30days); - } - if timestamp - >= (Utc::now() - chrono::Duration::seconds(ONE_YEAR as i64)).timestamp() - { - // 1-year time frame - amount_totals_1year = process_fee(amount.clone(), &amount_totals_1year); - bridge_fee_totals_1year = - process_fee(bridge_fee.clone(), &bridge_fee_totals_1year); - chain_fee_totals_1year = - process_fee(chain_fee.clone(), &chain_fee_totals_1year); - } - } - } - Err(err) => { - error!("RocksDB iterator error: {}", err); - } - } - } - - let response_data = TimeFrameData { - time_frames: vec![ - TimeFrame { - period: "1 day".to_string(), - amount_totals: amount_totals_1day, - bridge_fee_totals: bridge_fee_totals_1day, - chain_fee_totals: chain_fee_totals_1day, - }, - TimeFrame { - period: "7 days".to_string(), - amount_totals: amount_totals_7days, - bridge_fee_totals: bridge_fee_totals_7days, - chain_fee_totals: chain_fee_totals_7days, - }, - TimeFrame { - period: "30 days".to_string(), - amount_totals: amount_totals_30days, - bridge_fee_totals: bridge_fee_totals_30days, - chain_fee_totals: chain_fee_totals_30days, - }, - TimeFrame { - period: "1 year".to_string(), - amount_totals: amount_totals_1year, - bridge_fee_totals: bridge_fee_totals_1year, - chain_fee_totals: chain_fee_totals_1year, - }, - TimeFrame { - period: "All time".to_string(), - amount_totals: amount_totals_alltime, - bridge_fee_totals: bridge_fee_totals_alltime, - chain_fee_totals: chain_fee_totals_alltime, - }, - ], - }; - - HttpResponse::Ok().json(response_data) -} diff --git a/gravity-info-server/src/transactions/mod.rs b/gravity-info-server/src/transactions/mod.rs deleted file mode 100644 index 9ba59cb..0000000 --- a/gravity-info-server/src/transactions/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod database; -pub mod endpoints; diff --git a/gravity-info-server/src/volume.rs b/gravity-info-server/src/volume.rs deleted file mode 100644 index 7842f53..0000000 --- a/gravity-info-server/src/volume.rs +++ /dev/null @@ -1,271 +0,0 @@ -//! This file computes the total volume of Gravity bridge over daily, weekly, and monthly periods, this is an extremely time consuming task -//! becuase we iterate over the metadata of all erc20 in the bridge this task depends on the fast get info loop completing first - -use actix_web::cookie::time::Instant; -use actix_web::rt::System; -use clarity::Uint256; -use futures::future::join3; -use futures::future::join_all; -use gravity_utils::error::GravityError; -use log::{info, warn}; -use serde::Serialize; -use std::{ - sync::{Arc, RwLock}, - thread, - time::Duration, -}; -use web30::client::Web3; -use web30::types::Log; - -use crate::gravity_info::{get_erc20_metadata, get_gravity_info, Erc20Metadata, ETH_NODE_RPC}; -use clarity::Address as EthAddress; - -// update once a day -const LOOP_TIME: Duration = Duration::from_secs(86400); -const REQUEST_TIMEOUT: Duration = Duration::from_secs(30); -const BLOCKS_PER_DAY: u128 = 7_200; - -#[derive(Debug, Clone, Serialize)] -pub struct BridgeVolumeNumbers { - pub daily_volume: f64, - pub daily_inflow: f64, - pub daily_outflow: f64, - pub weekly_volume: f64, - pub weekly_inflow: f64, - pub weekly_outflow: f64, - pub monthly_volume: f64, - pub monthly_inflow: f64, - pub monthly_outflow: f64, -} - -lazy_static! { - static ref VOLUME: Arc>> = Arc::new(RwLock::new(None)); -} - -fn set_volume_info(input: BridgeVolumeNumbers) { - let mut r = VOLUME.write().unwrap(); - *r = Some(input); -} - -pub fn get_volume_info() -> Option { - VOLUME.read().unwrap().clone() -} - -pub fn bridge_volume_thread() { - info!("Starting volume computation thread"); - - thread::spawn(move || loop { - let runner = System::new(); - runner.block_on(async move { - let web3 = Web3::new(ETH_NODE_RPC, REQUEST_TIMEOUT); - let metadata = get_erc20_metadata(); - let params = get_gravity_info(); - if let (Some(metadata), Some(params)) = (metadata, params) { - let gravity_contract_address = params.params.bridge_ethereum_address; - let latest_block = match web3.eth_block_number().await { - Ok(v) => v, - Err(e) => { - warn!("Failed to get ETH block number with {:?}", e); - return; - } - }; - let starting_block_daily = latest_block - BLOCKS_PER_DAY.into(); - let starting_block_weekly = latest_block - (BLOCKS_PER_DAY * 7).into(); - let starting_block_monthly = latest_block - (BLOCKS_PER_DAY * 30).into(); - let daily_volume = get_bridge_volume_for_range( - starting_block_daily, - latest_block, - &metadata, - gravity_contract_address, - &web3, - ); - let weekly_volume = get_bridge_volume_for_range( - starting_block_weekly, - latest_block, - &metadata, - gravity_contract_address, - &web3, - ); - let monthly_volume = get_bridge_volume_for_range( - starting_block_monthly, - latest_block, - &metadata, - gravity_contract_address, - &web3, - ); - info!("Starting volume query"); - let start = Instant::now(); - let (daily_volume, weekly_volume, monthly_volume) = - join3(daily_volume, weekly_volume, monthly_volume).await; - match (daily_volume, weekly_volume, monthly_volume) { - (Ok(daily), Ok(weekly), Ok(monthly)) => { - set_volume_info(BridgeVolumeNumbers { - daily_volume: daily.volume, - daily_inflow: daily.inflow, - daily_outflow: daily.outflow, - weekly_volume: weekly.volume, - weekly_inflow: weekly.inflow, - weekly_outflow: weekly.outflow, - monthly_volume: monthly.volume, - monthly_inflow: monthly.inflow, - monthly_outflow: monthly.outflow, - }); - info!( - "Successfuly updated volume info in {}s!", - start.elapsed().as_seconds_f32() - ); - } - (Err(e), _, _) => warn!("Could not get daily volume {:?}", e), - (_, Err(e), _) => warn!("Could not get weekly volume {:?}", e), - (_, _, Err(e)) => warn!("Could not get monthly volume {:?}", e), - } - } - }); - if get_volume_info().is_some() { - thread::sleep(LOOP_TIME); - } else { - // we haven't gotten any info yet, try again soon - thread::sleep(Duration::from_secs(5)); - } - }); -} - -#[derive(Debug, Clone, Serialize, Default)] -struct BridgeVolume { - volume: f64, - inflow: f64, - outflow: f64, -} - -/// Gets the bridge volume across all tokens for a provided block range -async fn get_bridge_volume_for_range( - starting_block: Uint256, - ending_block: Uint256, - metadata: &[Erc20Metadata], - gravity_contract_address: EthAddress, - web3: &Web3, -) -> Result { - // total volume in usdc - let mut volume = 0u8.into(); - let mut inflow = 0u8.into(); - let mut outflow = 0u8.into(); - let mut futs = Vec::new(); - for token in metadata { - let vol = get_gravity_volume_for_token( - starting_block, - ending_block, - token, - gravity_contract_address, - web3, - ); - futs.push(vol); - } - let futs = join_all(futs).await; - for f in futs { - let f = f?; - volume += f.volume; - inflow += f.inflow; - outflow += f.outflow; - } - Ok(BridgeVolume { - volume, - inflow, - outflow, - }) -} - -/// Gets the volume of the Gravity contract over the provided -/// number of blocks for a given erc20 -async fn get_gravity_volume_for_token( - starting_block: Uint256, - ending_block: Uint256, - erc20: &Erc20Metadata, - gravity_contract_address: EthAddress, - web3: &Web3, -) -> Result { - if let Some(exchange_rate) = erc20.exchange_rate { - let mut volume: f64 = 0u8.into(); - let mut inflow: f64 = 0u8.into(); - let mut outflow: f64 = 0u8.into(); - - let decimals: u32 = erc20.decimals.to_string().parse().unwrap(); - let exchange_rate: f64 = exchange_rate.to_string().parse().unwrap(); - info!("Searching events for {}", erc20.symbol); - // tiny block range becuase of the huge amount of events - // these contracts prodcue - let blocks_to_search: Uint256 = 500u16.into(); - let mut current_block = starting_block; - while current_block + blocks_to_search < ending_block { - let logs = web3 - .check_for_events( - current_block, - Some(current_block + blocks_to_search), - vec![erc20.address], - vec!["Transfer(address,address,uint256)"], - ) - .await?; - - let (v, i, o) = sum_logs(logs, gravity_contract_address, decimals, exchange_rate)?; - volume += v; - inflow += i; - outflow += o; - - current_block += blocks_to_search; - } - let logs = web3 - .check_for_events( - current_block, - Some(ending_block), - vec![erc20.address], - vec!["Transfer(address,address,uint256)"], - ) - .await?; - let (v, i, o) = sum_logs(logs, gravity_contract_address, decimals, exchange_rate)?; - volume += v; - inflow += i; - outflow += o; - - Ok(BridgeVolume { - volume, - inflow, - outflow, - }) - } else { - // no exchange rate, ignore - Ok(BridgeVolume::default()) - } -} - -fn sum_logs( - logs: Vec, - gravity_contract_address: EthAddress, - decimals: u32, - exchange_rate: f64, -) -> Result<(f64, f64, f64), GravityError> { - let mut volume: f64 = 0u8.into(); - let mut inflow: f64 = 0u8.into(); - let mut outflow: f64 = 0u8.into(); - for l in logs { - let from = EthAddress::from_slice(&l.topics[1][12..32])?; - let to = EthAddress::from_slice(&l.topics[2][12..32])?; - let amount = Uint256::from_be_bytes(&l.data[0..32]); - if amount > u128::MAX.into() { - warn!("Found contract deploy!"); - continue; - } - // unit conversion to get to whole dollars float caveats about - // rounding errors apply - let amount: f64 = amount.to_string().parse().unwrap(); - let amount = amount / 10u128.pow(decimals) as f64; - let amount = amount * exchange_rate; - let amount = amount / 10u128.pow(6) as f64; - if to == gravity_contract_address { - volume += amount; - inflow += amount - } else if from == gravity_contract_address { - volume += amount; - outflow += amount; - } - } - Ok((volume, inflow, outflow)) -} diff --git a/scripts/build-and-deploy.sh b/scripts/build-and-deploy.sh index a4d201f..3eb9e48 100644 --- a/scripts/build-and-deploy.sh +++ b/scripts/build-and-deploy.sh @@ -2,19 +2,19 @@ set -eux DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -pushd $DIR/../gravity-info-server +pushd $DIR/../althea-info-server set +e -rm ../scripts/gravity-info-server +rm ../scripts/althea-info-server set -e cargo build --release -cp target/release/gravity-info-server ../scripts +cp target/release/althea-info-server ../scripts popd -pushd $DIR/../gravity-info-dash +pushd $DIR/../althea-info-dash yarn run build -rm -rf ../scripts/gravity-info-dash/ -mkdir ../scripts/gravity-info-dash -cp -r build/* ../scripts/gravity-info-dash +rm -rf ../scripts/althea-info-dash/ +mkdir ../scripts/althea-info-dash +cp -r build/* ../scripts/althea-info-dash popd pushd $DIR diff --git a/scripts/roles/setup-info-server/tasks/main.yml b/scripts/roles/setup-info-server/tasks/main.yml index 71a9d29..92c026a 100644 --- a/scripts/roles/setup-info-server/tasks/main.yml +++ b/scripts/roles/setup-info-server/tasks/main.yml @@ -2,7 +2,7 @@ - name: Stop info-server systemd: - name: gravity-info-server + name: althea-info-server state: stopped become: true # just in case we haven't deployed the service yet @@ -10,8 +10,8 @@ - name: Copy binary copy: - src: "{{playbook_dir}}/gravity-info-server" - dest: /usr/bin/gravity-info-server + src: "{{playbook_dir}}/althea-info-server" + dest: /usr/bin/althea-info-server mode: 0755 become: true diff --git a/scripts/roles/setup-info-server/tasks/systemd.yml b/scripts/roles/setup-info-server/tasks/systemd.yml index 1ff88a5..224c148 100644 --- a/scripts/roles/setup-info-server/tasks/systemd.yml +++ b/scripts/roles/setup-info-server/tasks/systemd.yml @@ -1,14 +1,14 @@ --- - name: Template service file template: - src: gravity-info-server.service.j2 - dest: /etc/systemd/system/gravity-info-server.service + src: althea-info-server.service.j2 + dest: /etc/systemd/system/althea-info-server.service become: true - name: Set the info server to run on startup systemd: daemon_reload: yes - name: gravity-info-server + name: althea-info-server state: restarted enabled: yes become: true @@ -18,16 +18,16 @@ seconds: 10 - name: Check if the info server is running - command: systemctl status gravity-info-server - ignore_errors: yes + command: systemctl status althea-info-server + ignore_errors: true changed_when: false register: service_gravity_info_server_status -- name: Report status of Gravity info server +- name: Report status of Althea info server fail: msg: | - Service gravity-info-server is not running. - Output of `systemctl status gravity-info-server`: + Service althea-info-server is not running. + Output of `systemctl status althea-info-server`: {{ service_gravity_info_server_status.stdout }} {{ service_gravity_info_server_status.stderr }} when: service_gravity_info_server_status is failed \ No newline at end of file