Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[release] Kintsugi 2.32.2 #1223

Merged
merged 14 commits into from
May 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env.dev
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ REACT_APP_FEATURE_FLAG_LENDING=enabled
REACT_APP_FEATURE_FLAG_AMM=enabled
REACT_APP_FEATURE_FLAG_WALLET=enabled
REACT_APP_FEATURE_FLAG_BANXA=enabled

REACT_APP_FEATURE_FLAG_EARN_STRATEGIES=enabled

/* DEVELOPMENT */

Expand Down
91 changes: 73 additions & 18 deletions api/health.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import dateutil.parser
from datetime import datetime
from dateutil.tz import tzutc
from flask import Flask, jsonify
from flask import Flask, jsonify, abort


class Oracle:
Expand Down Expand Up @@ -80,30 +80,85 @@ def isHealthy(self):
return status["chainHeightDiff"] < 3 and status["secondsDiff"] < 7200 # 2hrs


KSM_URL = "https://api-kusama.interlay.io/graphql/graphql"
INTR_URL = "https://api.interlay.io/graphql/graphql"

app = Flask(__name__)

class Vault:
def __init__(self, baseUrl) -> None:
self.baseUrl = baseUrl

@app.route("/_health/ksm/oracle", methods=["GET"])
def get_ksm_oracle_health():
return jsonify(Oracle(KSM_URL, "KSM").isHealthy())
def _latestVaults(self):
q = """
query MyQuery {
vaults(limit: 10, orderBy: registrationBlock_active_DESC) {
id
registrationTimestamp
}
}
"""
payload = {"query": q, "variables": None}
resp = requests.post(self.baseUrl, json=payload)
return resp.json()["data"]["vaults"]

def isHealthy(self):
vaults = self._latestVaults()
return len(self._latestVaults()) > 0

@app.route("/_health/ksm/relay", methods=["GET"])
def get_ksm_relayer_health():
return jsonify(Relayer(KSM_URL).isHealthy())

KSM_URL = "https://api-kusama.interlay.io/graphql/graphql"
INTR_URL = "https://api.interlay.io/graphql/graphql"
TESTNET_INTR = "https://api-testnet.interlay.io/graphql/graphql"
TESTNET_KINT = "https://api-dev-kintsugi.interlay.io/graphql/graphql"

@app.route("/_health/intr/oracle", methods=["GET"])
def get_intr_oracle_health():
return jsonify(Oracle(INTR_URL, "DOT").isHealthy())
app = Flask(__name__)


@app.route("/_health/intr/relay", methods=["GET"])
def get_intr_relayer_health():
return jsonify(Relayer(INTR_URL).isHealthy())
@app.route("/_health/<chain>/oracle", methods=["GET"])
def get_oracle_health(chain):
def oracle():
if chain == "kint":
return Oracle(KSM_URL, "KSM")
elif chain == "intr":
return Oracle(INTR_URL, "DOT")
elif chain == "testnet_kint":
return Oracle(TESTNET_KINT, "KSM")
elif chain == "testnet_intr":
return Oracle(TESTNET_INTR, "DOT")
else:
abort(404)

return jsonify(oracle().isHealthy())


@app.route("/_health/<chain>/relay", methods=["GET"])
def get_relay_health(chain):
def relay():
if chain == "kint":
return Relayer(KSM_URL)
elif chain == "intr":
return Relayer(INTR_URL)
elif chain == "testnet_kint":
return Relayer(TESTNET_KINT)
elif chain == "testnet_intr":
return Relayer(TESTNET_INTR)
else:
abort(404)

return jsonify(relay().isHealthy())


@app.route("/_health/<chain>/vault", methods=["GET"])
def get_vault_health(chain):
def vault():
if chain == "kint":
return Vault(KSM_URL)
elif chain == "intr":
return Vault(INTR_URL)
elif chain == "testnet_kint":
return Vault(TESTNET_KINT)
elif chain == "testnet_intr":
return Vault(TESTNET_INTR)
else:
abort(404)

return jsonify(vault().isHealthy())


if __name__ == "__main__":
Expand Down
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"name": "interbtc-ui",
"version": "2.32.0",
"version": "2.32.2",
"private": true,
"dependencies": {
"@craco/craco": "^6.1.1",
"@headlessui/react": "^1.1.1",
"@heroicons/react": "^2.0.0",
"@interlay/bridge": "^0.3.9",
"@interlay/interbtc-api": "2.2.2",
"@interlay/monetary-js": "0.7.2",
"@heroicons/react": "^2.0.18",
"@interlay/bridge": "^0.3.10",
"@interlay/interbtc-api": "2.2.4",
"@interlay/monetary-js": "0.7.3",
"@polkadot/api": "9.14.2",
"@polkadot/extension-dapp": "0.44.1",
"@polkadot/react-identicon": "^2.11.1",
Expand Down
13 changes: 10 additions & 3 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import TestnetBanner from './legacy-components/TestnetBanner';
import { FeatureFlags, useFeatureFlag } from './utils/hooks/use-feature-flag';

const Bridge = React.lazy(() => import(/* webpackChunkName: 'bridge' */ '@/pages/Bridge'));
const EarnStrategies = React.lazy(() => import(/* webpackChunkName: 'earn-strategies' */ '@/pages/EarnStrategies'));
const Transfer = React.lazy(() => import(/* webpackChunkName: 'transfer' */ '@/pages/Transfer'));
const Transactions = React.lazy(() => import(/* webpackChunkName: 'transactions' */ '@/pages/Transactions'));
const TX = React.lazy(() => import(/* webpackChunkName: 'tx' */ '@/pages/TX'));
Expand All @@ -35,9 +36,9 @@ const Vaults = React.lazy(() => import(/* webpackChunkName: 'vaults' */ '@/pages
// TODO: last task will be to delete legacy dashboard and rename vault dashboard
const Vault = React.lazy(() => import(/* webpackChunkName: 'vault' */ '@/pages/Vaults/Vault'));
const Loans = React.lazy(() => import(/* webpackChunkName: 'loans' */ '@/pages/Loans'));
const Swap = React.lazy(() => import(/* webpackChunkName: 'loans' */ '@/pages/AMM'));
const Pools = React.lazy(() => import(/* webpackChunkName: 'loans' */ '@/pages/AMM/Pools'));
const Wallet = React.lazy(() => import(/* webpackChunkName: 'loans' */ '@/pages/Wallet'));
const Swap = React.lazy(() => import(/* webpackChunkName: 'amm' */ '@/pages/AMM'));
const Pools = React.lazy(() => import(/* webpackChunkName: 'amm/pools' */ '@/pages/AMM/Pools'));
const Wallet = React.lazy(() => import(/* webpackChunkName: 'wallet' */ '@/pages/Wallet'));
const Actions = React.lazy(() => import(/* webpackChunkName: 'actions' */ '@/pages/Actions'));
const NoMatch = React.lazy(() => import(/* webpackChunkName: 'no-match' */ '@/pages/NoMatch'));

Expand All @@ -50,6 +51,7 @@ const App = (): JSX.Element => {
const isLendingEnabled = useFeatureFlag(FeatureFlags.LENDING);
const isAMMEnabled = useFeatureFlag(FeatureFlags.AMM);
const isWalletEnabled = useFeatureFlag(FeatureFlags.WALLET);
const isEarnStrategiesEnabled = useFeatureFlag(FeatureFlags.EARN_STRATEGIES);

// Loads the connection to the faucet - only for testnet purposes
const loadFaucet = React.useCallback(async (): Promise<void> => {
Expand Down Expand Up @@ -212,6 +214,11 @@ const App = (): JSX.Element => {
<Wallet />
</Route>
)}
{isEarnStrategiesEnabled && (
<Route path={PAGES.EARN_STRATEGIES}>
<EarnStrategies />
</Route>
)}
<Route path={PAGES.ACTIONS}>
<Actions />
</Route>
Expand Down
1 change: 1 addition & 0 deletions src/assets/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
"issue": "Issue",
"redeem": "Redeem",
"nav_bridge": "Bridge",
"nav_earn_strategies": "Earn Strategies",
"nav_transfer": "Transfer",
"nav_lending": "Lending",
"nav_swap": "Swap",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { ISubmittableResult } from '@polkadot/types/types';
import clsx from 'clsx';
import { useTranslation } from 'react-i18next';
import { FaCheckCircle } from 'react-icons/fa';
import { useMutation, useQueryClient } from 'react-query';
import { useQueryClient } from 'react-query';
import { toast } from 'react-toastify';

import { BTC_EXPLORER_TRANSACTION_API } from '@/config/blockstream-explorer-links';
Expand All @@ -16,7 +15,7 @@ import { TABLE_PAGE_LIMIT } from '@/utils/constants/general';
import { QUERY_PARAMETERS } from '@/utils/constants/links';
import { KUSAMA, POLKADOT } from '@/utils/constants/relay-chain-names';
import { getColorShade } from '@/utils/helpers/colors';
import { submitExtrinsicPromise } from '@/utils/helpers/extrinsic';
import { Transaction, useTransaction } from '@/utils/hooks/transaction';
import useQueryParams from '@/utils/hooks/use-query-params';

import ManualIssueExecutionUI from '../ManualIssueExecutionUI';
Expand All @@ -34,21 +33,15 @@ const ConfirmedIssueRequest = ({ request }: Props): JSX.Element => {
const selectedPageIndex = selectedPage - 1;

const queryClient = useQueryClient();
// TODO: should type properly (`Relay`)
const executeMutation = useMutation<ISubmittableResult, Error, any>(
(variables: any) => {
if (!variables.backingPayment.btcTxId) {
throw new Error('Bitcoin transaction ID not identified yet.');
}
return submitExtrinsicPromise(window.bridge.issue.execute(variables.id, variables.backingPayment.btcTxId));
},
{
onSuccess: (_, variables) => {
queryClient.invalidateQueries([ISSUES_FETCHER, selectedPageIndex * TABLE_PAGE_LIMIT, TABLE_PAGE_LIMIT]);
toast.success(t('issue_page.successfully_executed', { id: variables.id }));
}

// TODO: check if this transaction is necessary
const transaction = useTransaction(Transaction.ISSUE_EXECUTE, {
onSuccess: (_, variables) => {
const [requestId] = variables.args;
queryClient.invalidateQueries([ISSUES_FETCHER, selectedPageIndex * TABLE_PAGE_LIMIT, TABLE_PAGE_LIMIT]);
toast.success(t('issue_page.successfully_executed', { id: requestId }));
}
);
});

return (
<>
Expand Down Expand Up @@ -82,16 +75,14 @@ const ConfirmedIssueRequest = ({ request }: Props): JSX.Element => {
</p>
<ManualIssueExecutionUI request={request} />
</RequestWrapper>
{executeMutation.isError && executeMutation.error && (
{transaction.isError && transaction.error && (
<ErrorModal
open={!!executeMutation.error}
open={!!transaction.error}
onClose={() => {
executeMutation.reset();
transaction.reset();
}}
title='Error'
description={
typeof executeMutation.error === 'string' ? executeMutation.error : executeMutation.error.message
}
description={typeof transaction.error === 'string' ? transaction.error : transaction.error.message}
/>
)}
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ import {
newAccountId,
newMonetaryAmount
} from '@interlay/interbtc-api';
import { ISubmittableResult } from '@polkadot/types/types';
import clsx from 'clsx';
import { useTranslation } from 'react-i18next';
import { useMutation, useQuery, useQueryClient } from 'react-query';
import { useQuery, useQueryClient } from 'react-query';
import { toast } from 'react-toastify';

import { displayMonetaryAmount } from '@/common/utils/utils';
Expand All @@ -21,7 +20,7 @@ import { TABLE_PAGE_LIMIT } from '@/utils/constants/general';
import { QUERY_PARAMETERS } from '@/utils/constants/links';
import { KUSAMA, POLKADOT } from '@/utils/constants/relay-chain-names';
import { getColorShade } from '@/utils/helpers/colors';
import { submitExtrinsicPromise } from '@/utils/helpers/extrinsic';
import { Transaction, useTransaction } from '@/utils/hooks/transaction';
import useQueryParams from '@/utils/hooks/use-query-params';

// TODO: issue requests should not be typed here but further above in the app
Expand Down Expand Up @@ -57,21 +56,13 @@ const ManualIssueExecutionUI = ({ request }: Props): JSX.Element => {

const queryClient = useQueryClient();

// TODO: should type properly (`Relay`)
const executeMutation = useMutation<ISubmittableResult, Error, any>(
(variables: any) => {
if (!variables.backingPayment.btcTxId) {
throw new Error('Bitcoin transaction ID not identified yet.');
}
return submitExtrinsicPromise(window.bridge.issue.execute(variables.id, variables.backingPayment.btcTxId));
},
{
onSuccess: (_, variables) => {
queryClient.invalidateQueries([ISSUES_FETCHER, selectedPageIndex * TABLE_PAGE_LIMIT, TABLE_PAGE_LIMIT]);
toast.success(t('issue_page.successfully_executed', { id: variables.id }));
}
const transaction = useTransaction(Transaction.ISSUE_EXECUTE, {
onSuccess: (_, variables) => {
const [requestId] = variables.args;
queryClient.invalidateQueries([ISSUES_FETCHER, selectedPageIndex * TABLE_PAGE_LIMIT, TABLE_PAGE_LIMIT]);
toast.success(t('issue_page.successfully_executed', { id: requestId }));
}
);
});

const { data: vaultCapacity, error: vaultCapacityError } = useQuery({
queryKey: 'vault-capacity',
Expand All @@ -91,7 +82,12 @@ const ManualIssueExecutionUI = ({ request }: Props): JSX.Element => {

// TODO: should type properly (`Relay`)
const handleExecute = (request: any) => () => {
executeMutation.mutate(request);
if (!request.backingPayment.btcTxId) {
console.error('Bitcoin transaction ID not identified yet.');
return;
}

transaction.execute(request.id, request.backingPayment.btcTxId);
};

const backingPaymentAmount = newMonetaryAmount(request.backingPayment.amount, WRAPPED_TOKEN);
Expand Down Expand Up @@ -135,24 +131,22 @@ const ManualIssueExecutionUI = ({ request }: Props): JSX.Element => {
)}
<InterlayDenimOrKintsugiMidnightOutlinedButton
className='w-full'
pending={executeMutation.isLoading}
pending={transaction.isLoading}
disabled={!executable || !isOwner}
onClick={handleExecute(request)}
>
{t('issue_page.claim_interbtc', {
wrappedTokenSymbol: WRAPPED_TOKEN_SYMBOL
})}
</InterlayDenimOrKintsugiMidnightOutlinedButton>
{executeMutation.isError && executeMutation.error && (
{transaction.isError && transaction.error && (
<ErrorModal
open={!!executeMutation.error}
open={!!transaction.error}
onClose={() => {
executeMutation.reset();
transaction.reset();
}}
title='Error'
description={
typeof executeMutation.error === 'string' ? executeMutation.error : executeMutation.error.message
}
description={typeof transaction.error === 'string' ? transaction.error : transaction.error.message}
/>
)}
</div>
Expand Down
Loading