setIsDropDown(!isDropdown)}
+ className="col-3 d-flex justify-content-end cursor-pointer"
+ onClick={toggleCollapse}
>
@@ -114,7 +129,7 @@ export default function NetworkItem({
{renderAmount()}
{handleNetworkLink && (
-
)}
- {isDropdown &&
{children}}
+
+ {(children && !isCollapsed) &&
{children}}
>
);
}
return (
{renderType()}
diff --git a/components/profile/pages/payments.tsx b/components/profile/pages/payments.tsx
index ffc3c467ff..0f0c09434b 100644
--- a/components/profile/pages/payments.tsx
+++ b/components/profile/pages/payments.tsx
@@ -15,14 +15,22 @@ import {useAppState} from "contexts/app-state";
import {formatNumberToCurrency} from "helpers/formatNumber";
+import { Network } from "interfaces/network";
import {Payment} from "interfaces/payments";
import {getCoinPrice} from "services/coingecko";
import useApi from "x-hooks/use-api";
+export interface TotalFiatNetworks {
+ tokenAddress: string;
+ value: number;
+ price: number;
+ networkId: number;
+}
+
export default function PaymentsPage() {
- const { t } = useTranslation(["common", "profile"]);
+ const { t } = useTranslation(["common", "profile", "custom-network"]);
const defaultOptions = [
{
@@ -39,8 +47,10 @@ export default function PaymentsPage() {
},
];
- const [totalEuro, setTotalEuro] = useState(0);
+ const [totalFiat, setTotalFiat] = useState(0);
+ const [totalFiatNetworks, setTotalFiatNetworks] = useState
([])
const [payments, setPayments] = useState([]);
+ const [networks, setNetworks] = useState([]);
const [hasNoConvertedToken, setHasNoConvertedToken] = useState(false);
const {state} = useAppState();
@@ -62,27 +72,43 @@ export default function PaymentsPage() {
}
useEffect(() => {
- if (!state.currentUser?.walletAddress || !state.Service?.network?.active?.name) return;
+ if (!state.currentUser?.walletAddress) return;
+
+ getPayments(state.currentUser.walletAddress, startDate, endDate).then(setPayments);
+ }, [state.currentUser?.walletAddress, startDate, endDate]);
- getPayments(state.currentUser.walletAddress, state.Service?.network?.active.name, startDate, endDate)
- .then(setPayments);
- }, [state.currentUser?.walletAddress, state.Service?.network?.active?.name, startDate, endDate]);
+ useEffect(() => {
+ if (!payments) return;
+ const allNetworks: Network[] = [];
+ payments.map((payment) => {
+ if (
+ !networks.find((network) => network?.id === payment?.issue?.network?.id) &&
+ !allNetworks.find((network) => network?.id === payment?.issue?.network?.id)
+ ) {
+ allNetworks.push(payment?.issue?.network);
+ setNetworks(allNetworks);
+ }
+ });
+ }, [payments]);
useEffect(() => {
if (!payments?.length) return;
Promise.all(payments.map(async (payment) => ({
- tokenAddress: payment.issue.transactionalToken.address,
+ tokenAddress: payment?.issue?.transactionalToken?.address,
value: payment.ammount,
- price: await getCoinPrice(payment.issue.transactionalToken.symbol, state?.Settings.currency.defaultFiat),
+ price: await getCoinPrice(payment?.issue?.transactionalToken?.symbol, state?.Settings.currency.defaultFiat),
+ networkId: payment?.issue?.network_id
}))).then((tokens) => {
const totalConverted = tokens.reduce((acc, token) => acc + token.value * (token.price || 0),
0);
const noConverted = !!tokens.find((token) => token.price === undefined);
-
- setTotalEuro(totalConverted);
+
+ setTotalFiatNetworks(tokens)
+ setTotalFiat(totalConverted);
setHasNoConvertedToken(noConverted);
});
+
}, [payments]);
function onChangeDate(e: ChangeEvent,
@@ -112,10 +138,10 @@ export default function PaymentsPage() {
- {formatNumberToCurrency(totalEuro)}
+ {formatNumberToCurrency(totalFiat)}
- {t("currencies.euro")}
+ {state?.Settings?.currency?.defaultFiat}
>
)}
@@ -168,9 +194,14 @@ export default function PaymentsPage() {
-
- {payments?.length > 0 ? (
-
+
+ {networks?.length > 0 ? (
+
) : (
)}
@@ -179,4 +210,4 @@ export default function PaymentsPage() {
);
-}
\ No newline at end of file
+}
diff --git a/components/profile/pages/voting-power.tsx b/components/profile/pages/voting-power.tsx
deleted file mode 100644
index b7483cd202..0000000000
--- a/components/profile/pages/voting-power.tsx
+++ /dev/null
@@ -1,113 +0,0 @@
-import {useEffect} from "react";
-import {Col, Row} from "react-bootstrap";
-
-import BigNumber from "bignumber.js";
-import {useTranslation} from "next-i18next";
-import { useRouter } from "next/router";
-
-import OracleIcon from "assets/icons/oracle-icon";
-
-import Delegations from "components/delegations";
-import InfoTooltip from "components/info-tooltip";
-import OraclesActions from "components/oracles-actions";
-import OraclesDelegate from "components/oracles-delegate";
-import ProfileLayout from "components/profile/profile-layout";
-import TokenBalance from "components/profile/token-balance";
-import {FlexRow} from "components/profile/wallet-balance";
-import ReadOnlyButtonWrapper from "components/read-only-button-wrapper";
-
-import {useAppState} from "contexts/app-state";
-
-import {formatStringToCurrency} from "helpers/formatNumber";
-
-import {useAuthentication} from "x-hooks/use-authentication";
-
-export default function VotingPowerPage() {
- const { t } = useTranslation(["common", "profile"]);
-
- const { state } = useAppState();
- const { updateWalletBalance } = useAuthentication();
-
- const { curatorAddress } = useRouter().query;
-
- const oracleToken = {
- symbol: t("$oracles", { token: state.Service?.network?.active?.networkToken?.symbol }),
- name: t("profile:oracle-name-placeholder"),
- icon:
- };
-
- const oraclesLocked = state.currentUser?.balance?.oracles?.locked || BigNumber("0");
- const oraclesDelegatedToMe = state.currentUser?.balance?.oracles?.delegatedByOthers || BigNumber("0");
-
- useEffect(() => { updateWalletBalance(true) }, []);
-
- return(
-
-
-
-
-
- {t("$oracles", { token: state.Service?.network?.active?.networkToken?.symbol })}
-
-
-
- {t("misc.total")}
-
-
- {formatStringToCurrency(oraclesLocked.plus(oraclesDelegatedToMe).toFixed())}
-
-
-
-
-
-
-
-
-
-
- updateWalletBalance(true) }
- />
-
- updateWalletBalance(true) }
- defaultAddress={curatorAddress?.toString()}
- />
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
\ No newline at end of file
diff --git a/components/profile/pages/voting-power/index.tsx b/components/profile/pages/voting-power/index.tsx
new file mode 100644
index 0000000000..27b6b21904
--- /dev/null
+++ b/components/profile/pages/voting-power/index.tsx
@@ -0,0 +1,40 @@
+import {Col} from "react-bootstrap";
+
+import {useTranslation} from "next-i18next";
+import { useRouter } from "next/router";
+
+import If from "components/If";
+import VotingPowerMultiNetwork from "components/profile/pages/voting-power//voting-power-multi-network";
+import VotingPowerNetwork from "components/profile/pages/voting-power/voting-power-network";
+import ProfileLayout from "components/profile/profile-layout";
+import {FlexRow} from "components/profile/wallet-balance";
+import ReadOnlyButtonWrapper from "components/read-only-button-wrapper";
+
+export default function VotingPowerPage() {
+ const { query } = useRouter();
+ const { t } = useTranslation(["common", "profile"]);
+
+ const { network } = query;
+
+ const isOnNetwork = !!network;
+
+ return(
+
+
+
+
+ {t("profile:voting-power")}
+
+
+ }
+ >
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/components/profile/pages/voting-power/total-votes.tsx b/components/profile/pages/voting-power/total-votes.tsx
new file mode 100644
index 0000000000..853c4be5f3
--- /dev/null
+++ b/components/profile/pages/voting-power/total-votes.tsx
@@ -0,0 +1,104 @@
+import { ReactNode } from "react";
+
+import { BigNumber } from "bignumber.js";
+import clsx from "clsx";
+import { useTranslation } from "next-i18next";
+
+import InfoTooltip from "components/info-tooltip";
+import NetworkItem from "components/profile/network-item";
+import { FlexRow } from "components/profile/wallet-balance";
+
+import { formatStringToCurrency } from "helpers/formatNumber";
+
+interface TotalVotesProps {
+ votesLocked: BigNumber;
+ votesDelegatedToMe: BigNumber;
+ icon: string | ReactNode;
+ tokenName: string;
+ tokenColor?: string;
+ tokenSymbol: string;
+ votesSymbol: string;
+ variant?: "network" | "multi-network";
+}
+
+export default function TotalVotes({
+ votesLocked,
+ votesDelegatedToMe,
+ icon,
+ tokenName,
+ tokenSymbol,
+ votesSymbol,
+ variant = "network",
+ tokenColor
+} : TotalVotesProps) {
+ const { t } = useTranslation(["common", "profile"]);
+
+ function getTextColorProps() {
+ if (tokenColor)
+ return {
+ style: {
+ color: tokenColor
+ }
+ };
+
+ return {
+ className: "text-primary"
+ };
+ }
+
+ function getAmountItem(amount) {
+ return ;
+ }
+
+ return(
+
+
+
+ {t("profile:total-votes")}
+
+
+
+
+ {formatStringToCurrency(votesLocked.plus(votesDelegatedToMe).toFixed())}
+
+
+
+ {votesSymbol}
+
+
+
+
+
+
+
+ {t("profile:locked-by-me")}
+
+
+ {getAmountItem(votesLocked.toFixed())}
+
+
+ {t("profile:deletaged-to-me")}
+
+
+ {getAmountItem(votesDelegatedToMe.toFixed())}
+
+ );
+}
\ No newline at end of file
diff --git a/components/profile/pages/voting-power/voting-power-multi-network.tsx b/components/profile/pages/voting-power/voting-power-multi-network.tsx
new file mode 100644
index 0000000000..7d47d656e8
--- /dev/null
+++ b/components/profile/pages/voting-power/voting-power-multi-network.tsx
@@ -0,0 +1,109 @@
+import { useEffect, useState } from "react";
+
+import BigNumber from "bignumber.js";
+import { useTranslation } from "next-i18next";
+import { useRouter } from "next/router";
+
+import { ContextualSpan } from "components/contextual-span";
+import Delegations from "components/delegations";
+import If from "components/If";
+import Indicator from "components/indicator";
+import NetworkColumns from "components/profile/network-columns";
+import NetworkItem from "components/profile/network-item";
+import TotalVotes from "components/profile/pages/voting-power/total-votes";
+
+import { useAppState } from "contexts/app-state";
+
+import useApi from "x-hooks/use-api";
+import { useNetwork } from "x-hooks/use-network";
+
+export default function VotingPowerMultiNetwork() {
+ const { push } = useRouter();
+ const { t } = useTranslation(["common", "profile"]);
+
+ const [networks, setNetworks] = useState([]);
+
+ const { state } = useAppState();
+ const { searchCurators } = useApi();
+ const { getURLWithNetwork } = useNetwork();
+
+ function goToNetwork(network) {
+ return () => {
+ push(getURLWithNetwork("/bounties", {
+ network: network?.name,
+ chain: network?.chain?.chainShortName
+ }));
+ };
+ }
+
+ useEffect(() => {
+ if (state.currentUser?.walletAddress)
+ searchCurators({
+ address: state.currentUser?.walletAddress
+ })
+ .then(({ rows }) => setNetworks(rows))
+ .catch(error => console.debug("Failed to fetch voting power data", error));
+ }, [state.currentUser?.walletAddress]);
+
+ return(
+ <>
+
+
+ {t("profile:need-network-to-manage")}
+
+
+
+
+
+
+
+ { !!networks.length && networks.map(({ tokensLocked, delegatedToMe, delegations, network }) =>
+
+
+
}
+ tokenColor={network?.colors?.primary}
+ tokenName={network?.networkToken?.name}
+ tokenSymbol={network?.networkToken?.symbol}
+ votesSymbol={`${network?.networkToken?.symbol} ${t("misc.votes")}`}
+ variant="multi-network"
+ />
+
+
+
+
+
+ )
+ }
+
+
+ >
+ );
+}
\ No newline at end of file
diff --git a/components/profile/pages/voting-power/voting-power-network.tsx b/components/profile/pages/voting-power/voting-power-network.tsx
new file mode 100644
index 0000000000..d8c9bcc525
--- /dev/null
+++ b/components/profile/pages/voting-power/voting-power-network.tsx
@@ -0,0 +1,88 @@
+import { useEffect } from "react";
+import { Row } from "react-bootstrap";
+
+import BigNumber from "bignumber.js";
+import { useTranslation } from "next-i18next";
+import { useRouter } from "next/router";
+
+import Delegations from "components/delegations";
+import { Divider } from "components/divider";
+import Indicator from "components/indicator";
+import OraclesActions from "components/oracles-actions";
+import OraclesDelegate from "components/oracles-delegate";
+import TotalVotes from "components/profile/pages/voting-power/total-votes";
+
+import { useAppState } from "contexts/app-state";
+
+import { useAuthentication } from "x-hooks/use-authentication";
+import useChain from "x-hooks/use-chain";
+
+export default function VotingPowerNetwork() {
+ const { query } = useRouter();
+ const { t } = useTranslation(["common", "profile"]);
+
+ const { state } = useAppState();
+ const { updateWalletBalance } = useAuthentication();
+ const { chain } = useChain();
+
+ const { curatorAddress } = query;
+
+ const oracleToken = {
+ symbol: state.Service?.network?.active?.networkToken?.symbol || t("misc.token"),
+ name: state.Service?.network?.active?.networkToken?.name || t("profile:oracle-name-placeholder"),
+ icon:
+ };
+
+ const votesSymbol = t("token-votes", { token: oracleToken.symbol })
+
+ const oraclesLocked = state.currentUser?.balance?.oracles?.locked || BigNumber("0");
+ const oraclesDelegatedToMe = state.currentUser?.balance?.oracles?.delegatedByOthers || BigNumber("0");
+
+ useEffect(() => {
+ if(!state.currentUser?.walletAddress || !state.Service?.active?.network || !chain) return;
+
+ updateWalletBalance(true);
+ }, [state.currentUser?.walletAddress, state.Service?.active?.network, chain]);
+
+ return(
+ <>
+
+
+
+ updateWalletBalance(true) }
+ />
+
+ updateWalletBalance(true) }
+ defaultAddress={curatorAddress?.toString()}
+ />
+
+
+
+
+
+
+
+ >
+ );
+}
\ No newline at end of file
diff --git a/components/profile/payment-item.tsx b/components/profile/payment-item.tsx
index fc4d2869f8..fb6c134a21 100644
--- a/components/profile/payment-item.tsx
+++ b/components/profile/payment-item.tsx
@@ -15,7 +15,7 @@ export default function PaymentItem({
handleItemClick,
}: Payment) {
const CONTAINER_CLASSES = [
- "justify-content-between align-items-center bg-transparent",
+ "justify-content-between align-items-center bg-gray-950",
"border border-dark-gray border-radius-8 mb-2 py-3 px-4",
];
@@ -38,7 +38,15 @@ export default function PaymentItem({
- handleItemClick(issue?.issueId)} outline>
+
+ handleItemClick(issue?.issueId,
+ issue?.network?.chain?.chainShortName,
+ issue?.network?.name)
+ }
+ outline
+ >
{labelBounty} #{issue?.issueId}
diff --git a/components/profile/payments-list.tsx b/components/profile/payments-list.tsx
index 218fc56ce6..08b7f29cdb 100644
--- a/components/profile/payments-list.tsx
+++ b/components/profile/payments-list.tsx
@@ -3,38 +3,84 @@ import { useRouter } from "next/router";
import PaymentItem from "components/profile/payment-item";
+import { Network } from "interfaces/network";
import { Payment } from "interfaces/payments";
-import { useNetwork} from "x-hooks/use-network";
+import { useNetwork } from "x-hooks/use-network";
+
+import NetworkColumns from "./network-columns";
+import NetworkItem from "./network-item";
+import { TotalFiatNetworks } from "./pages/payments";
+import { FlexColumn } from "./wallet-balance";
interface PaymentsListProps {
payments: Payment[];
+ networks: Network[];
+ totalNetworks: TotalFiatNetworks[];
+ symbol: string;
}
// TODO: Add InfiniteScroll and pagination
-export default function PaymentsList({ payments }: PaymentsListProps) {
+export default function PaymentsList({
+ payments,
+ networks,
+ totalNetworks,
+ symbol
+}: PaymentsListProps) {
const { push } = useRouter();
const { t } = useTranslation(["common", "profile", "bounty"]);
const { getURLWithNetwork } = useNetwork();
- function handleItemClick(issueId: string) {
- const [repoId, id] = issueId.split('/')
+ function handleItemClick(issueId: string, chainName: string, networkName: string) {
+ const [repoId, id] = issueId.split("/");
+
+ push(getURLWithNetwork("/bounty", { id, repoId, chain: chainName, network: networkName}));
+ }
- push(getURLWithNetwork('/bounty', { id, repoId }));
+ function handleAmount(networkId: number) {
+ return totalNetworks
+ .filter((n) => n?.networkId === networkId)
+ .reduce((acc, token) => acc + token.value * (token.price || 0), 0);
}
- if (!payments) return null;
+ if (!payments || !networks) return null;
return (
<>
- {payments &&
- payments?.map((payment: Payment) =>
- PaymentItem({
- ...payment,
- labelToken: t("misc.$token"),
- labelBounty: t("bounty:label"),
- handleItemClick
- }))}
+
+ {networks &&
+ networks?.map((network, key) => (
+ {
+ push(getURLWithNetwork("/", { chain: network?.chain?.chainShortName, network: network?.name }))
+ }}
+ amount={handleAmount(network?.id)}
+ symbol={symbol}
+ >
+
+ {payments &&
+ payments
+ ?.filter((p) => network?.id === p?.issue?.network?.id)
+ .map((payment: Payment) =>
+ PaymentItem({
+ ...payment,
+ labelToken: t("misc.$token"),
+ labelBounty: t("bounty:label"),
+ handleItemClick,
+ }))}
+
+
+ ))}
>
);
-}
+}
\ No newline at end of file
diff --git a/components/profile/profile-layout.tsx b/components/profile/profile-layout.tsx
index 10455b4029..9fa05a65f2 100644
--- a/components/profile/profile-layout.tsx
+++ b/components/profile/profile-layout.tsx
@@ -1,19 +1,7 @@
-import { useEffect } from "react";
-
import ConnectWalletButton from "components/connect-wallet-button";
import ProfileSide from "components/profile/profile-side";
-import { useAppState } from "contexts/app-state";
-import { changeNeedsToChangeChain } from "contexts/reducers/change-spinners";
-
export default function ProfileLayout({ children }) {
- const { state, dispatch } = useAppState();
-
- useEffect(() => {
- if (state.currentUser?.walletAddress && !state.connectedChain?.matchWithNetworkChain)
- dispatch(changeNeedsToChangeChain(true));
- }, [state.currentUser?.walletAddress, state.connectedChain?.matchWithNetworkChain]);
-
return(
<>
diff --git a/components/profile/profile-router.tsx b/components/profile/profile-router.tsx
index c9701c1c79..ff2f940482 100644
--- a/components/profile/profile-router.tsx
+++ b/components/profile/profile-router.tsx
@@ -15,7 +15,7 @@ export default function ProfileRouter() {
const { asPath, push } = useRouter();
const Route = (path, page) => ({ path, page });
-
+
const routes = [
Route("/profile", ProfilePage),
Route("/profile/wallet", WalletPage),
diff --git a/components/profile/token-balance.tsx b/components/profile/token-balance.tsx
index c11f6c7877..5bf4c2f003 100644
--- a/components/profile/token-balance.tsx
+++ b/components/profile/token-balance.tsx
@@ -12,37 +12,50 @@ import { TokenInfo } from "interfaces/token";
export type TokenBalanceType = Partial;
interface TokenBalanceProps {
- type: "token" | "oracle" | "delegation";
+ type?: "token" | "oracle" | "delegation";
delegation?: DelegationExtended;
overSymbol?: string;
+ tokenColor?: string;
+ variant?: "network" | "multi-network";
onTakeBackClick?: () => void;
}
-export default function TokenBalance({
- icon,
- name,
- symbol,
+export default function TokenBalance({
+ icon,
+ name,
+ symbol,
balance,
- type,
+ type = "token",
delegation,
overSymbol,
- onTakeBackClick
+ onTakeBackClick,
+ tokenColor,
+ variant = "network"
} : TokenBalanceType & TokenBalanceProps) {
const { t } = useTranslation(["common"]);
const CONTAINER_CLASSES = [
"justify-content-between align-items-center bg-transparent",
- "border border-dark-gray border-radius-8 mb-2 py-3 px-4"
+ "border border-gray-800 border-radius-4 mb-2 py-3 px-4",
+ variant === "network" ? "bg-gray-900" : "bg-gray-950"
];
- const symbolColor = {
- token: "primary",
- oracle: "purple",
- delegation: "purple"
- };
+ function getTextColorProps(classes) {
+ if (tokenColor)
+ return {
+ style: {
+ color: tokenColor
+ },
+ className: classes
+ };
- const delegationSymbol = delegation &&
- <>{formatStringToCurrency(BigNumber(balance).toFixed())}{symbol}>;
+ return {
+ className: `${classes} text-primary`
+ };
+ }
+
+ const delegationSymbol = delegation &&
+ <>{formatStringToCurrency(BigNumber(balance).toFixed())}{symbol}>;
return (
@@ -52,19 +65,33 @@ export default function TokenBalance({
- {overSymbol ? overSymbol : (delegationSymbol || symbol)}
- {delegation?.to || name}
+
+ {overSymbol ? overSymbol : (delegationSymbol || symbol)}
+
+ {delegation?.to || name}
- {type === "delegation" &&
-
+ {(type === "delegation" && onTakeBackClick) &&
+
{t("actions.take-back")}
- ||
+
+ }
+
+ { type !== "delegation" &&
<>
- {formatStringToCurrency(BigNumber(balance).toFixed())}
- {symbol}
+
+ {formatStringToCurrency(BigNumber(balance).toFixed())}
+
+
+ {symbol}
+
>
}
diff --git a/components/profile/wallet-balance.tsx b/components/profile/wallet-balance.tsx
index e41146e2a9..a92a3c1c02 100644
--- a/components/profile/wallet-balance.tsx
+++ b/components/profile/wallet-balance.tsx
@@ -1,22 +1,37 @@
-import {useEffect, useState} from "react";
+import {ReactElement, useEffect, useState} from "react";
import BigNumber from "bignumber.js";
import {useTranslation} from "next-i18next";
-
-import OracleIcon from "assets/icons/oracle-icon";
+import { useRouter } from "next/router";
import InfoTooltip from "components/info-tooltip";
-import TokenBalance, {TokenBalanceType} from "components/profile/token-balance";
+import {TokenBalanceType} from "components/profile/token-balance";
+import SelectChainDropdown from "components/select-chain-dropdown";
import TokenIcon from "components/token-icon";
import {useAppState} from "contexts/app-state";
import {formatStringToCurrency} from "helpers/formatNumber";
+import { SupportedChainData } from "interfaces/supported-chain-data";
import { Token } from "interfaces/token";
-import {getCoinInfoByContract} from "services/coingecko";
+import {getCoinInfoByContract, getCoinPrice} from "services/coingecko";
+
+import useApi from "x-hooks/use-api";
+import { useNetwork } from "x-hooks/use-network";
+import useNetworkChange from "x-hooks/use-network-change";
+
+import NetworkItem from "./network-item";
+interface TokensOracles {
+ symbol: string;
+ name: string;
+ networkName: string;
+ icon: string | ReactElement;
+ oraclesLocked: BigNumber;
+ address: string;
+}
export const FlexRow = ({children, className = ""}) =>
{children}
;
@@ -27,25 +42,23 @@ export default function WalletBalance() {
const { t } = useTranslation(["common", "profile"]);
const [totalAmount, setTotalAmount] = useState("0");
- const [oracleToken, setOracleToken] = useState({
- symbol: "",
- name: "",
- icon:
- });
+ const [tokensOracles, setTokensOracles] = useState([]);
const [tokens, setTokens] = useState([]);
const [hasNoConvertedToken, setHasNoConvertedToken] = useState(false);
const { state } = useAppState();
- const oraclesLocked = state.currentUser?.balance?.oracles?.locked || BigNumber(0);
- const oraclesDelegatedToMe = state.currentUser?.balance?.oracles?.delegatedByOthers || BigNumber(0);
+ const { searchCurators, getTokens } = useApi();
+ const { getURLWithNetwork } = useNetwork();
+ const { handleAddNetwork } = useNetworkChange();
+ const { query, push } = useRouter();
const getAddress = (token: string | Token) => typeof token === "string" ? token : token?.address;
async function processToken(token: string | Token) {
const [tokenData, balance] = await Promise.all([
- typeof token === "string" ? state.Service.active.getERC20TokenData(token) : token,
- state.Service.active.getTokenBalance(getAddress(token), state.currentUser.walletAddress)
+ typeof token === "string" ? state.Service?.active?.getERC20TokenData(token) : token,
+ state.Service?.active?.getTokenBalance(getAddress(token), state.currentUser.walletAddress)
]);
const tokenInformation = await getCoinInfoByContract(tokenData.symbol);
@@ -57,64 +70,95 @@ export default function WalletBalance() {
};
}
+ async function handleNetworkSelected(chain: SupportedChainData) {
+ handleAddNetwork(chain).catch((e) => console.log('Handle Add Network Error', e));
+ }
+
function loadBalances() {
- const networkToken = state.Service?.network?.active?.networkToken;
- const registryTokenAddress = state.Service?.active?.registry?.token?.contractAddress?.toLowerCase();
-
- if (!state.currentUser?.walletAddress ||
- !registryTokenAddress ||
- !networkToken?.address ||
- !state.connectedChain?.matchWithNetworkChain)
- return;
-
- const isSameToken = registryTokenAddress === networkToken.address;
-
- Promise.all([
- isSameToken ? Promise.resolve(null) : processToken(registryTokenAddress),
- processToken(networkToken.address)
- ]).then(tokens => {
- setOracleToken({
- symbol: t("$oracles", { token: networkToken?.symbol }),
- name: networkToken?.name,
- icon:
- })
-
- setTokens(tokens.filter(v => !!v));
+ if(!state.currentUser?.walletAddress) return;
+
+ searchCurators({
+ address: state.currentUser?.walletAddress,
+ networkName: query?.network?.toString() || "",
+ chainShortName: query?.chain?.toString() || state?.connectedChain?.shortName,
+ }).then(({ rows }) => {
+ Promise.all(rows?.map(async (curator) => {
+ const tokenInformation = await getCoinInfoByContract(curator?.network?.networkToken?.symbol);
+
+ return ({
+ symbol: t("$oracles", { token: curator?.network?.networkToken?.symbol }),
+ name: `${t("misc.locked")} ${curator?.network?.networkToken?.name}`,
+ address: curator?.network?.networkToken?.address,
+ icon: ,
+ oraclesLocked: BigNumber(curator.tokensLocked),
+ networkName: curator?.network?.name,
+ })
+ })).then(setTokensOracles)
+ })
+
+ if(state.Service?.starting) return;
+
+ getTokens(state?.connectedChain?.id, query?.network?.toString() || "").then((tokens) => {
+ Promise.all(tokens?.map(async (token) => {
+ const tokenData = await processToken(token?.address)
+ return { networks: token?.networks, ...tokenData }
+ })).then(setTokens);
});
}
useEffect(loadBalances, [
state.currentUser?.walletAddress,
- state.Service?.active?.registry?.token?.contractAddress,
- state.Service?.active?.network?.contractAddress,
- state.connectedChain?.matchWithNetworkChain
+ state.connectedChain,
+ state.Service?.starting
]);
useEffect(() => {
if (!tokens.length) return;
- const totalConverted = tokens.reduce((acc, token) => BigNumber(token.balance)
- .multipliedBy(token.prices?.eur || 0)
- .plus(acc), BigNumber(0));
- const totalTokens = tokens.reduce((acc, token) => BigNumber(token.balance).plus(acc), BigNumber(0));
- const noConverted = !!tokens.find(token => token.prices?.eur === undefined);
-
- setTotalAmount(noConverted ? totalTokens.toFixed() : totalConverted.toFixed());
- setHasNoConvertedToken(noConverted);
-
+ Promise.all(tokens.map(async (token) => ({
+ tokenAddress: token.address,
+ value:
+ typeof token.balance === "string"
+ ? BigNumber(token.balance)
+ : token.balance,
+ price: await getCoinPrice(token?.symbol,
+ state?.Settings.currency.defaultFiat),
+ }))).then((tokens) => {
+ const totalConverted = tokens.reduce((acc, token) =>
+ BigNumber(token.value)
+ .multipliedBy(token.price || 0)
+ .plus(acc),
+ BigNumber(0));
+ const noConverted = !!tokens.find((token) => token.price === undefined);
+ const totalTokens = tokens.reduce((acc, token) => BigNumber(token.value).plus(acc), BigNumber(0));
+
+ setTotalAmount(noConverted ? totalTokens.toFixed() : totalConverted.toFixed());
+ setHasNoConvertedToken(noConverted);
+ });
}, [tokens]);
return(
+
+ {t("profile:wallet")}
+
+ {!query?.network && (
+
+
+
+ )}
- {t("profile:balance")}
-
+ {t("profile:tokens")}
- {t("misc.total")}
-
+ {t("labels.recivedintotal")}
+
{formatStringToCurrency(totalAmount)}
- {!hasNoConvertedToken ? t("currencies.euro") : t("misc.token_other")}
+ {!hasNoConvertedToken ? state?.Settings?.currency?.defaultFiat : t("misc.token_other")}
-
- {tokens.map(token => )}
+ {tokens.map((token) => (
+
+ ))}
- {oracleToken?.symbol}
+ {t("main-nav.nav-avatar.voting-power")}
-
-
- {t("misc.total")}
-
- {formatStringToCurrency(oraclesLocked?.plus(oraclesDelegatedToMe)?.toFixed())}
-
-
-
-
-
+ {tokensOracles &&
+ tokensOracles?.map((token, key) => (
+ }
+ networkName={token?.name}
+ subNetworkText={token?.networkName}
+ handleNetworkLink={query?.network ? null : () => {
+ push(getURLWithNetwork("/", { chain: state?.connectedChain?.shortName, network: token?.networkName }))
+ }}
+ amount={token?.oraclesLocked.toFixed()}
+ symbol={token?.symbol}
+ />
+ ))}
);
}
\ No newline at end of file
diff --git a/components/proposal-action-card.tsx b/components/proposal-action-card.tsx
index 6c9a37b525..fc39089094 100644
--- a/components/proposal-action-card.tsx
+++ b/components/proposal-action-card.tsx
@@ -57,6 +57,14 @@ export default function ProposalActionCard({
branchProtectionRules[state.currentBounty?.data?.branch]?.requiredApprovingReviewCount || 0 : 0;
const approvalsCurrentPr = currentPullRequest?.approvals?.total || 0;
const prsNeedsApproval = approvalsCurrentPr < approvalsRequired;
+ const isPrOwner = (
+ currentPullRequest?.userAddress?.toLowerCase() ===
+ state.currentUser?.walletAddress?.toLowerCase()
+ )
+ const isProposalOwner = (
+ proposal?.creator?.toLowerCase() ===
+ state.currentUser?.walletAddress?.toLowerCase()
+ )
const proposalCanBeDisputed = () => [
isProposalDisputable(proposal?.contractCreationDate,
@@ -91,6 +99,8 @@ export default function ProposalActionCard({
!isDisputing,
allowMergeCommit === true,
!prsNeedsApproval,
+ !isPrOwner,
+ !isProposalOwner
// state.Service?.network?.active?.allowMerge === true
].every(v => v);
@@ -215,6 +225,22 @@ export default function ProposalActionCard({
|| ""
}
+ {(isPrOwner && !chainDisputable && !proposalCanBeDisputed()) && (
+
+
+ {t("proposal:messages.owner-pull-request")}
+
+
+ )}
+
+ {(isProposalOwner && !chainDisputable && !proposalCanBeDisputed()) && (
+
+
+ {t("proposal:messages.owner-proposal")}
+
+
+ )}
+
{ allowMergeCommit === false &&
diff --git a/components/seo.tsx b/components/seo.tsx
index 99f173da2b..5ff68caf55 100644
--- a/components/seo.tsx
+++ b/components/seo.tsx
@@ -4,6 +4,7 @@ import removeMarkdown from "markdown-to-text";
import {DefaultSeo, NextSeo} from "next-seo";
import SEO_CONFIG from "next-seo-config";
import getConfig from "next/config";
+import { useRouter } from "next/router";
import {useAppState} from "contexts/app-state";
@@ -16,14 +17,16 @@ interface ISeoProps {
}
const Seo: React.FC = () => {
- const {state} = useAppState();
+ const {query} = useRouter();
const [issueMeta, setIssueMeta] = useState(null);
- useEffect(() => {
+ const {state} = useAppState();
+
+ useEffect(() => {
setIssueMeta(state.currentBounty?.data);
}, [state.currentBounty?.data]);
- if (issueMeta?.issueId) {
+ if (issueMeta?.issueId && query?.id && query?.repoId) {
// eslint-disable-next-line no-unsafe-optional-chaining
const homeUrl = publicRuntimeConfig?.urls?.home;
// eslint-disable-next-line no-unsafe-optional-chaining
diff --git a/components/setup/call-to-action.tsx b/components/setup/call-to-action.tsx
index df8e281778..001e06eca1 100644
--- a/components/setup/call-to-action.tsx
+++ b/components/setup/call-to-action.tsx
@@ -19,13 +19,15 @@ export function CallToAction({
className="mb-3"
isAlert
>
- {call}
+ {call}
+
+ onClick={onClick}
+ >
{action}
diff --git a/components/wrong-network-modal.tsx b/components/wrong-network-modal.tsx
index 3351f2ef7e..dd1ee6847b 100644
--- a/components/wrong-network-modal.tsx
+++ b/components/wrong-network-modal.tsx
@@ -40,23 +40,24 @@ export default function WrongNetworkModal() {
state: { connectedChain, currentUser, Service, supportedChains, loading, spinners }
} = useAppState();
- const canBeHided = ![
+ const isRequired = [
pathname?.includes("new-network"),
- pathname?.includes("profile")
+ pathname?.includes("/[network]/[chain]/profile")
].some(c => c);
+ const canBeHided = !isRequired;
+
function changeShowModal() {
- if (!supportedChains?.length ||
- loading?.isLoading ||
- !spinners?.needsToChangeChain) {
+ if (!supportedChains?.length || loading?.isLoading) {
setShowModal(false);
return;
}
- if (typeof connectedChain?.matchWithNetworkChain !== "boolean" && !!currentUser?.walletAddress)
- setShowModal(connectedChain?.name === UNSUPPORTED_CHAIN);
- else
- setShowModal(!connectedChain?.matchWithNetworkChain && !!currentUser?.walletAddress);
+ setShowModal([
+ spinners?.needsToChangeChain,
+ connectedChain?.matchWithNetworkChain === false && isRequired,
+ connectedChain?.name === UNSUPPORTED_CHAIN && isRequired
+ ].some(c => c));
}
async function selectSupportedChain(chain: SupportedChainData) {
@@ -113,10 +114,11 @@ export default function WrongNetworkModal() {
connectedChain?.id,
supportedChains,
loading,
- spinners
+ spinners,
+ isRequired
]);
- if (spinners?.needsToChangeChain && !currentUser?.walletAddress)
+ if ((spinners?.needsToChangeChain || _showModal) && !currentUser?.walletAddress)
return ;
return (
diff --git a/db/migrations/20230324164005-add-delegated-to-me-column-to-curators.js b/db/migrations/20230324164005-add-delegated-to-me-column-to-curators.js
new file mode 100644
index 0000000000..8a03cdb83d
--- /dev/null
+++ b/db/migrations/20230324164005-add-delegated-to-me-column-to-curators.js
@@ -0,0 +1,15 @@
+'use strict';
+
+module.exports = {
+ async up (queryInterface, Sequelize) {
+ await queryInterface.addColumn("curators", "delegatedToMe", {
+ type: Sequelize.STRING,
+ allowNull: true,
+ defaultValue: "0"
+ });
+ },
+
+ async down (queryInterface, Sequelize) {
+ await queryInterface.removeColumn("curators", "delegatedToMe");
+ }
+};
diff --git a/db/migrations/20230327121403-create-delegations-table.js b/db/migrations/20230327121403-create-delegations-table.js
new file mode 100644
index 0000000000..75cd19be10
--- /dev/null
+++ b/db/migrations/20230327121403-create-delegations-table.js
@@ -0,0 +1,148 @@
+'use strict';
+
+const { Web3Connection, Network_v2 } = require("@taikai/dappkit");
+
+const ChainModel = require("../models/chain.model");
+const NetworkModel = require("../models/network.model");
+const CuratorsModel = require("../models/curator-model");
+const IssueModel = require("../models/issue.model");
+const RepositoryModel = require("../models/repositories.model");
+const PullRequestModel = require("../models/pullRequest.model");
+const MergeProposalModel = require("../models/mergeproposal");
+const TokenModel = require("../models/tokens.model");
+const DelegationModel = require("../models/delegation.model");
+
+module.exports = {
+ async up (queryInterface, Sequelize) {
+ await queryInterface.createTable("delegations", {
+ id: {
+ type: Sequelize.INTEGER,
+ autoIncrement: true,
+ primaryKey: true,
+ unique: true
+ },
+ from: {
+ type: Sequelize.STRING,
+ allowNull: false,
+ defaultValue: "0x0000000000000000000000000000000000000000"
+ },
+ to: {
+ type: Sequelize.STRING,
+ allowNull: false,
+ defaultValue: "0x0000000000000000000000000000000000000000"
+ },
+ amount: {
+ type: Sequelize.STRING,
+ allowNull: false,
+ defaultValue: "0"
+ },
+ contractId: {
+ type: Sequelize.INTEGER,
+ allowNull: false
+ },
+ networkId: {
+ type: Sequelize.INTEGER,
+ references: {
+ model: "networks",
+ key: "id"
+ }
+ },
+ chainId: {
+ type: Sequelize.INTEGER,
+ references: {
+ model: "chains",
+ key: "chainId"
+ }
+ },
+ curatorId: {
+ type: Sequelize.INTEGER,
+ references: {
+ model: "curators",
+ key: "id"
+ }
+ },
+ createdAt: {
+ type: Sequelize.DATE,
+ defaultValue: new Date()
+ },
+ updatedAt: {
+ type: Sequelize.DATE,
+ defaultValue: new Date()
+ }
+ });
+
+ [
+ ChainModel,
+ NetworkModel,
+ CuratorsModel,
+ IssueModel,
+ RepositoryModel,
+ PullRequestModel,
+ MergeProposalModel,
+ TokenModel,
+ DelegationModel
+ ].forEach(model => model.init(queryInterface.sequelize));
+
+ [
+ ChainModel,
+ NetworkModel,
+ CuratorsModel
+ ].forEach(model => model.associate(queryInterface.sequelize.models));
+
+ const chains = await ChainModel.findAll({
+ include: [
+ {
+ association: "networks",
+ include: [
+ { association: "curators" }
+ ]
+ }
+ ]
+ });
+
+ if (!chains.length) return;
+
+ try {
+ for (const { chainId, chainRpc, networks } of chains) {
+ const web3Connection = new Web3Connection({
+ skipWindowAssignment: true,
+ web3Host: chainRpc,
+ });
+
+ await web3Connection.start();
+
+ for (const { networkAddress, curators } of networks) {
+ if (!curators.length) continue;
+
+ const networkV2 = new Network_v2(web3Connection, networkAddress);
+
+ await networkV2.loadContract();
+
+ for (const curator of curators) {
+ const delegationOf = await networkV2.getDelegationsOf(curator.address);
+
+ if (!delegationOf.length) continue;
+
+ const delegations = delegationOf.map(({ id, from, to, amount }) => ({
+ from,
+ to,
+ amount,
+ contractId: id,
+ networkId: curator.networkId,
+ chainId: chainId,
+ curatorId: curator.id,
+ }));
+
+ await queryInterface.bulkInsert("delegations", delegations);
+ }
+ }
+ }
+ } catch (error) {
+ console.log("Failed to read previous delegations: ", error.toString());
+ }
+ },
+
+ async down (queryInterface, Sequelize) {
+ await queryInterface.dropTable("delegations");
+ }
+};
diff --git a/db/models/curator-model.js b/db/models/curator-model.js
index 7473de2e51..1c519abbdd 100644
--- a/db/models/curator-model.js
+++ b/db/models/curator-model.js
@@ -30,6 +30,11 @@ class Curators extends Model {
type: DataTypes.STRING,
allowNull: true,
},
+ delegatedToMe: {
+ type: DataTypes.STRING,
+ allowNull: true,
+ defaultValue: "0"
+ },
networkId: {
type: DataTypes.INTEGER,
allowNull: false,
@@ -56,6 +61,12 @@ class Curators extends Model {
foreignKey: "networkId",
sourceKey: "id"
});
+
+ this.hasMany(models.delegation, {
+ foreignKey: "curatorId",
+ sourceKey: "id",
+ as: "delegations"
+ });
}
}
diff --git a/db/models/delegation.model.js b/db/models/delegation.model.js
new file mode 100644
index 0000000000..a398fa3f0f
--- /dev/null
+++ b/db/models/delegation.model.js
@@ -0,0 +1,87 @@
+"use strict";
+const { Model, DataTypes } = require("sequelize");
+
+class Delegation extends Model {
+ static init(sequelize) {
+ super.init({
+ id: {
+ type: DataTypes.INTEGER,
+ autoIncrement: true,
+ primaryKey: true,
+ unique: true
+ },
+ from: {
+ type: DataTypes.STRING,
+ allowNull: false,
+ defaultValue: "0"
+ },
+ to: {
+ type: DataTypes.STRING,
+ allowNull: false,
+ defaultValue: "0"
+ },
+ amount: {
+ type: DataTypes.STRING,
+ allowNull: false,
+ defaultValue: "0"
+ },
+ contractId: {
+ type: DataTypes.INTEGER,
+ allowNull: false
+ },
+ chainId: {
+ type: DataTypes.INTEGER,
+ references: {
+ model: "chain",
+ key: "chainId"
+ }
+ },
+ networkId: {
+ type: DataTypes.INTEGER,
+ references: {
+ model: "network",
+ key: "id"
+ }
+ },
+ curatorId: {
+ type: DataTypes.INTEGER,
+ references: {
+ model: "curator",
+ key: "id"
+ }
+ },
+ createdAt: {
+ type: DataTypes.DATE,
+ defaultValue: new Date()
+ },
+ updatedAt: {
+ type: DataTypes.DATE,
+ defaultValue: new Date()
+ }
+ }, {
+ sequelize,
+ modelName: "delegation",
+ tableName: "delegations"
+ });
+ }
+
+ static associate(models) {
+ this.belongsTo(models.curator, {
+ foreignKey: "curatorId",
+ sourceKey: "id"
+ });
+
+ this.belongsTo(models.network, {
+ foreignKey: "networkId",
+ sourceKey: "id"
+ });
+
+ this.belongsTo(models.chain, {
+ foreignKey: "chainId",
+ targetKey: "chainId",
+ as: "chain"
+ });
+ }
+}
+
+module.exports = Delegation;
\ No newline at end of file
diff --git a/db/models/index.js b/db/models/index.js
index 44b1e94de5..5a83da9ff6 100644
--- a/db/models/index.js
+++ b/db/models/index.js
@@ -21,6 +21,7 @@ import Chain from "./chain.model";
import ProposalDistributions from './proposal-distributions.model';
import HeaderInformation from './header-information';
import KycSession from './kyc-session.model'
+import Delegation from './delegation.model'
const Database = { sequelize: null };
@@ -49,6 +50,7 @@ Database.proposalDistributions = ProposalDistributions;
Database.chain = Chain;
Database.headerInformation = HeaderInformation;
Database.kycSession = KycSession;
+Database.delegation = Delegation;
Object.values(Database).forEach((model) => {
if (model?.init) {
diff --git a/helpers/formatNumber.ts b/helpers/formatNumber.ts
index e5d1d86b25..9672ee15e7 100644
--- a/helpers/formatNumber.ts
+++ b/helpers/formatNumber.ts
@@ -12,7 +12,7 @@ export const formatNumberToNScale = (number: number | string, fixed = 2, spacer
const bigNumber = new BigNumber(number);
if (bigNumber.lt(1e3))
- return bigNumber.toFixed( number < 1 ? (+number.toString().split(`.`)?.[1]?.length || 2) : fixed)
+ return bigNumber.toFixed( bigNumber.lt(1) ? (+number.toString().split(`.`)?.[1]?.length || 2) : fixed);
const units = ['K', 'M', 'B', 'T', 'Qa', 'Qi', 'Sx', 'Sp', 'Oc', 'No', 'Dc', 'Ud', 'Dd', 'Td', 'Qad', 'Qid', 'Sxd', 'Spd', 'Ocd', 'Nod', 'Vg', 'Uvg', 'Dvg']; // eslint-disable-line
const zeroes = Math.floor(bigNumber.dividedBy(1.0e+1).toFixed(0).toString().length); // eslint-disable-line
@@ -34,6 +34,6 @@ export const formatStringToCurrency = (numStr: string) => {
const [ rest, decimals ] = numStr.toString().split(".");
const decimalsStr = decimals ? `.${decimals}` : "";
-
+
return `${rest.replace(/\B(?=(\d{3})+(?!\d))/g, ",")}${decimalsStr}`;
}
\ No newline at end of file
diff --git a/helpers/handleNetworksValuesApi.ts b/helpers/handleNetworksValuesApi.ts
index 255713f552..b03a9d53b9 100644
--- a/helpers/handleNetworksValuesApi.ts
+++ b/helpers/handleNetworksValuesApi.ts
@@ -3,13 +3,19 @@ const handleNetwork = (issues) =>
.map((issue) => {
if(issue.network)
issue.network.dataValues = {
+ networkAddress: issue.network.networkAddress,
name: issue.network.name,
- logoIcon: issue.network.logoIcon,
+ logoIcon: issue.network.logoIcon,
colors: { primary: issue.network?.colors?.primary },
chain: {
chainId: issue.network?.chain?.chainId,
chainShortName: issue.network?.chain?.chainShortName,
color: issue.network?.chain?.color
+ },
+ networkToken: {
+ name: issue?.network?.networkToken?.name,
+ symbol: issue?.network?.networkToken?.symbol,
+ address: issue?.network?.networkToken?.address,
}
}
return issue
diff --git a/interfaces/curators.ts b/interfaces/curators.ts
index 6a46ea8659..9bc646a449 100644
--- a/interfaces/curators.ts
+++ b/interfaces/curators.ts
@@ -1,19 +1,37 @@
+import { Network } from "interfaces/network";
+import { SupportedChainData } from "interfaces/supported-chain-data";
+
export interface Curator {
- address: string;
- acceptedProposals?: number;
- disputedProposals?: number;
- tokensLocked?: string;
- networkId?: number;
- disputes?: number;
- isCurrentlyCurator?: boolean
+ address: string;
+ acceptedProposals?: number;
+ disputedProposals?: number;
+ tokensLocked?: string;
+ delegatedToMe?: string;
+ networkId?: number;
+ disputes?: number;
+ isCurrentlyCurator?: boolean;
+ delegations?: Delegation[];
+}
+
+export interface Delegation {
+ from: string;
+ to: string;
+ amount: string;
+ contractId: number;
+ networkId: number;
+ curatorId: number;
+ chainId: number;
+ network?: Network;
+ curator?: Curator;
+ chain?: SupportedChainData;
}
export interface SearchCuratorParams {
- page?: string;
- address?: string;
- isCurrentlyCurator?: boolean;
- networkName?: string;
- sortBy?: string;
- order?: string;
- chainShortName?: string;
+ page?: string;
+ address?: string;
+ isCurrentlyCurator?: boolean;
+ networkName?: string;
+ sortBy?: string;
+ order?: string;
+ chainShortName?: string;
}
\ No newline at end of file
diff --git a/interfaces/leaderboard.ts b/interfaces/leaderboard.ts
index b53f81f97d..b13019032a 100644
--- a/interfaces/leaderboard.ts
+++ b/interfaces/leaderboard.ts
@@ -9,7 +9,7 @@ export interface SearchLeaderBoard {
export interface LeaderBoard {
address: string;
- githubHandle?: string;
+ githubLogin?: string;
numberNfts?: number;
ownedBountiesOpened?: number;
ownedBountiesClosed?: number;
diff --git a/interfaces/payments.ts b/interfaces/payments.ts
index 2f2241df5c..0d1ef28e2c 100644
--- a/interfaces/payments.ts
+++ b/interfaces/payments.ts
@@ -9,5 +9,5 @@ export interface Payment {
transactionHash: string;
labelBounty?: string;
labelToken?: string;
- handleItemClick: (issueId: string) => void
+ handleItemClick: (issueId: string, chainName: string, networkName: string) => void
}
\ No newline at end of file
diff --git a/interfaces/token.ts b/interfaces/token.ts
index 4c10dcf3f5..040fc340fd 100644
--- a/interfaces/token.ts
+++ b/interfaces/token.ts
@@ -2,6 +2,8 @@ import { ReactElement } from "react";
import BigNumber from "bignumber.js";
+import { Network } from "../interfaces/network";
+
export type TokenType = 'reward' | 'transactional';
export interface Token {
@@ -9,6 +11,7 @@ export interface Token {
address: string;
name: string;
symbol: string;
+ networks?: Network[];
currentValue?: number | string;
tokenInfo?: TokenInfo;
balance?: string | BigNumber;
diff --git a/pages/api/payments/index.ts b/pages/api/payments/index.ts
index 39f88b8446..302a72ae18 100644
--- a/pages/api/payments/index.ts
+++ b/pages/api/payments/index.ts
@@ -4,7 +4,6 @@ import {Op} from "sequelize";
import models from "db/models";
-import {chainFromHeader} from "helpers/chain-from-header";
import {resJsonMessage} from "helpers/res-json-message";
import {LogAccess} from "middleware/log-access";
@@ -12,20 +11,11 @@ import {WithValidChainId} from "middleware/with-valid-chain-id";
import WithCors from "middleware/withCors";
async function get(req: NextApiRequest, res: NextApiResponse) {
- const {wallet, networkName, startDate, endDate} = req.query;
+ const {wallet, startDate, endDate} = req.query;
- const chain = await chainFromHeader(req);
+ const networks = await models.network.findAll({});
- const network = await models.network.findOne({
- where: {
- name: {
- [Op.iLike]: String(networkName).replaceAll(" ", "-")
- },
- chain_id: {[Op.eq]: +chain?.chainId}
- }
- });
-
- if (!network) return resJsonMessage("Invalid network", res, 404);
+ if (!networks) return resJsonMessage("Network not found", res, 404);
let filter: {
createdAt?: {
@@ -55,11 +45,19 @@ async function get(req: NextApiRequest, res: NextApiResponse) {
const payments = await models.userPayments.findAll({
include: [
- {
- association: "issue",
- where: { network_id: network.id },
- include:[{ association: "transactionalToken" }]
- }
+ {
+ association: "issue",
+ where: {
+ network_id: { [Op.in]: networks.map((network) => network.id) },
+ },
+ include: [
+ { association: "transactionalToken" },
+ {
+ association: "network",
+ include: [{ association: "chain", attributes: ["chainShortName"] }],
+ },
+ ],
+ },
],
where: {
address: {
diff --git a/pages/api/search/curators/index.ts b/pages/api/search/curators/index.ts
index 513c485b5f..08619c4c8c 100644
--- a/pages/api/search/curators/index.ts
+++ b/pages/api/search/curators/index.ts
@@ -1,38 +1,48 @@
-import {NextApiRequest, NextApiResponse} from "next";
-import {Op, WhereOptions} from "sequelize";
+import { NextApiRequest, NextApiResponse } from "next";
+import { Op, Sequelize, WhereOptions } from "sequelize";
import models from "db/models";
-import paginate, {calculateTotalPages} from "helpers/paginate";
-import {resJsonMessage} from "helpers/res-json-message";
+import handleNetworkValues from "helpers/handleNetworksValuesApi";
+import paginate, { calculateTotalPages } from "helpers/paginate";
+import { resJsonMessage } from "helpers/res-json-message";
-import {LogAccess} from "middleware/log-access";
-import {WithValidChainId} from "middleware/with-valid-chain-id";
+import { LogAccess } from "middleware/log-access";
+import { WithValidChainId } from "middleware/with-valid-chain-id";
import WithCors from "middleware/withCors";
-import {error} from "services/logging";
+import { error } from "services/logging";
async function get(req: NextApiRequest, res: NextApiResponse) {
try {
const whereCondition: WhereOptions = {};
- const { address, isCurrentlyCurator, networkName, page, chainShortName } = req.query || {};
+ const { address, isCurrentlyCurator, networkName, page, chainShortName } =
+ req.query || {};
+
+ let queryParams = {};
if (networkName) {
const network = await models.network.findOne({
where: {
name: {
[Op.iLike]: String(networkName).replaceAll(" ", "-"),
- }
+ },
},
include: [
- {
+ {
association: "chain",
where: {
- chainShortName: chainShortName
- }
- }
- ]
+ ...(chainShortName
+ ? {
+ chainShortName: Sequelize.where(Sequelize.fn("lower",
+ Sequelize.col("chain.chainShortName")),
+ chainShortName.toString().toLowerCase()),
+ }
+ : {}),
+ },
+ },
+ ],
});
if (!network) return resJsonMessage("Invalid network", res, 404);
@@ -40,7 +50,35 @@ async function get(req: NextApiRequest, res: NextApiResponse) {
whereCondition.networkId = network?.id;
}
- if (address) whereCondition.address = address;
+ queryParams = {
+ include: [
+ {
+ association: "network",
+ include: [
+ { association: "networkToken" },
+ {
+ association: "chain",
+ where: {
+ ...(chainShortName
+ ? {
+ chainShortName: Sequelize.where(Sequelize.fn("lower",
+ Sequelize.col("network.chain.chainShortName")),
+ chainShortName.toString().toLowerCase()),
+ }
+ : {}),
+ },
+ required: true,
+ },
+ ],
+ required: true,
+ },
+ { association: "delegations" },
+ ],
+ };
+
+ if (address)
+ whereCondition.address = Sequelize.where(Sequelize.fn("lower", Sequelize.col("curator.address")),
+ address.toString().toLowerCase());
if (isCurrentlyCurator)
whereCondition.isCurrentlyCurator = isCurrentlyCurator;
@@ -52,18 +90,21 @@ async function get(req: NextApiRequest, res: NextApiResponse) {
},
where: whereCondition,
nest: true,
+ ...queryParams,
},
req.query,
[[req.query.sortBy || "acceptedProposals", req.query.order || "DESC"]]))
.then(async (items) => {
return Promise.all(items.rows.map(async (item) => {
- item.dataValues.disputes =
- await models.dispute.count({
+ item.dataValues.disputes = await models.dispute.count({
where: { address: item.address },
- });
+ });
return item;
}))
- .then((values) => ({ count: items.count, rows: values }))
+ .then((values) => ({
+ count: items.count,
+ rows: handleNetworkValues(values),
+ }))
.catch(() => items);
});
@@ -73,7 +114,7 @@ async function get(req: NextApiRequest, res: NextApiResponse) {
pages: calculateTotalPages(curators.count),
});
} catch (e) {
- error(e)
+ error(e);
return res.status(500);
}
}
diff --git a/pages/api/search/issues/recent.ts b/pages/api/search/issues/recent.ts
index f3b6a31fe6..fc669eebab 100644
--- a/pages/api/search/issues/recent.ts
+++ b/pages/api/search/issues/recent.ts
@@ -6,22 +6,45 @@ import models from "db/models";
import {LogAccess} from "middleware/log-access";
import WithCors from "middleware/withCors";
-const getLastIssuesByStatus = async (state, whereCondition, sortBy, order, limit = 3) => (models.issue.findAll({
- where: {
- ...whereCondition,
- state,
- },
- order: [[ String(sortBy), String(order) ]],
- include: [
- {
- association: "network",
- include: [ { association: "chain" }]
+const handleWhereState = (state: string) => {
+ if(state === 'funding'){
+ return ({
+ [Op.and]: [
+ { state: { [Op.in]: ["draft", "open"] } },
+ { fundingAmount: { [Op.ne]: "0" } },
+ ],
+ })
+ }
+
+ if(state === 'open'){
+ return ({
+ state: state,
+ fundingAmount: { [Op.eq]: "0" }
+ })
+ }
+
+ return ({ state: state })
+}
+
+const getLastIssuesByStatus = async (state, whereCondition, sortBy, order, limit = 3) =>
+ models.issue.findAll({
+ where: {
+ ...whereCondition,
+ ...(state
+ ? handleWhereState(state)
+ : {}),
},
- { association: "repository" },
- { association: "transactionalToken" }
- ],
- limit
-}))
+ order: [[String(sortBy), String(order)]],
+ include: [
+ {
+ association: "network",
+ include: [{ association: "chain" }],
+ },
+ { association: "repository" },
+ { association: "transactionalToken" },
+ ],
+ limit,
+ });
async function get(req: NextApiRequest, res: NextApiResponse) {
const whereCondition: WhereOptions = {state: {[Op.not]: "pending"}};
@@ -29,6 +52,7 @@ async function get(req: NextApiRequest, res: NextApiResponse) {
repoId,
creator,
address,
+ state,
networkName,
sortBy,
order
@@ -65,12 +89,12 @@ async function get(req: NextApiRequest, res: NextApiResponse) {
whereCondition.network_id = {[Op.in]: networks.map(network => network.id)}
}
- const issuesOpen = await getLastIssuesByStatus("open",
- whereCondition,
- sortBy,
- order);
-
- return res.status(200).json(issuesOpen);
+ const issues = await getLastIssuesByStatus(state,
+ whereCondition,
+ sortBy,
+ order);
+
+ return res.status(200).json(issues);
}
async function getAll(req: NextApiRequest, res: NextApiResponse) {
diff --git a/pages/api/search/leaderboard/index.ts b/pages/api/search/leaderboard/index.ts
index e069d47d78..03a903e17e 100644
--- a/pages/api/search/leaderboard/index.ts
+++ b/pages/api/search/leaderboard/index.ts
@@ -41,7 +41,7 @@ async function get(req: NextApiRequest, res: NextApiResponse) {
const user = await models.user.findOne({
where: { address: item.address.toLowerCase() },
});
- item.dataValues.githubHandle = user?.githubHandle || null;
+ item.dataValues.githubLogin = user?.githubLogin || null;
return item;
}))
.then((values) => values)
@@ -51,7 +51,7 @@ async function get(req: NextApiRequest, res: NextApiResponse) {
const result = [];
result.push(...leaderboard.filter(({ address, dataValues }) =>
- [address, dataValues?.githubHandle].some((text) =>
+ [address, dataValues?.githubLogin].some((text) =>
searchPatternInText(text || "", String(search)))));
const paginatedData = paginateArray(result, 10, page || 1);
@@ -79,7 +79,7 @@ async function get(req: NextApiRequest, res: NextApiResponse) {
where: { address: item.address.toLowerCase() },
});
- item.dataValues.githubHandle = user?.githubHandle || null;
+ item.dataValues.githubLogin = user?.githubLogin || null;
return item;
}))
diff --git a/pages/api/search/tokens/index.ts b/pages/api/search/tokens/index.ts
index 49a0e4f109..139349f7c6 100644
--- a/pages/api/search/tokens/index.ts
+++ b/pages/api/search/tokens/index.ts
@@ -30,7 +30,6 @@ async function get(req: NextApiRequest, res: NextApiResponse) {
include: [
{
association: "networks",
- attributes: [],
required: true,
where: {
name: Sequelize.where(colToLower("networks.name"), "=", (networkName as string).toLowerCase())
@@ -38,6 +37,14 @@ async function get(req: NextApiRequest, res: NextApiResponse) {
}
]
};
+ } else {
+ queryParams = {
+ include: [
+ {
+ association: "networks",
+ },
+ ],
+ };
}
diff --git a/pages/create-bounty.tsx b/pages/create-bounty.tsx
index 874520754b..47f1c3f21c 100644
--- a/pages/create-bounty.tsx
+++ b/pages/create-bounty.tsx
@@ -403,6 +403,7 @@ export default function CreateBountyPage() {
searchNetworks({
isRegistered: true,
+ isClosed: false,
chainId: connectedChain?.id,
sortBy: "name",
order: "asc",
diff --git a/public/locales/en/bounty.json b/public/locales/en/bounty.json
index 5d75c71498..ef8467e4a9 100644
--- a/public/locales/en/bounty.json
+++ b/public/locales/en/bounty.json
@@ -127,6 +127,9 @@
"branch": "Branch"
},
"create-bounty": "Create Bounty",
+ "create-funding": "Create Funding Request",
+ "not-found-funding": "Funding requests make the community itself fund ideas they would like for their applications",
+ "not-found-bounty": "Not found recent bounties",
"next-step": "Next Step",
"bounty-created": "Bounty created",
"in-bounties": "in Bounties",
@@ -135,6 +138,7 @@
"sub-title-bounties": "A collection of the most recent bounties and MVP Networks on our ecosystem",
"most-active-networks": "Most Active Networks",
"recent-bounties": "Recent Bounties",
+ "recent-funding": "Recent Funding requests",
"all-bounties": "All Bounties",
"explore-all": "Explore All",
"recent-bounties-empty": "Not found recent bounties",
diff --git a/public/locales/en/common.json b/public/locales/en/common.json
index 5234665611..4165977e96 100644
--- a/public/locales/en/common.json
+++ b/public/locales/en/common.json
@@ -4,6 +4,7 @@
"bepro-votes": "Bepro Votes",
"$bepro": "BEPRO",
"bepro": "BEPRO",
+ "token-votes": "{{token}} Votes",
"please-wait": "Please wait",
"close": "Close",
"currencies": {
@@ -13,7 +14,7 @@
"filters": {
"filters": "Filter",
"search-repositories": "Search repositories",
- "repository": "repository",
+ "repository": "repository",
"all": "All",
"no-records-found": "No records found",
"clear-filter": "Clear filter",
@@ -62,7 +63,7 @@
"leaderboard": "Leaderboard",
"Oracle": "bv{{token}}",
"new-bounty": "New bounty",
- "explore": "Explore",
+ "explore": "Explore",
"get-started": "Get Started",
"connect": "Connect Wallet",
"new-network": "New Network",
@@ -191,7 +192,8 @@
"unkown": "Unknown",
"latest": "Latest",
"network": "Network",
- "unsupported": "Unsupported"
+ "unsupported": "Unsupported",
+ "votes": "Votes"
},
"modals": {
"help-modal": {
diff --git a/public/locales/en/my-oracles.json b/public/locales/en/my-oracles.json
index 0072447e72..400d09230c 100644
--- a/public/locales/en/my-oracles.json
+++ b/public/locales/en/my-oracles.json
@@ -1,33 +1,33 @@
{
- "how-to-use": "How to use bv{{token}} ?",
- "oracles-usage": "bv{{token}} can be used for Curators or as a requirement to create Distributions in the Network",
+ "how-to-use": "How to use Votes ?",
+ "oracles-usage": "Votes can be used for Curators or as a requirement to create Distributions in the Network",
"available": "Available",
"delegated": "Delegated",
"list-of-delegations": "List of Delegations",
"descriptions": {
- "oracles-delegated-to-others": "bv{{token}} delegated by me to others users",
- "oracles-delegated-to-me": "bv{{token}} delegated to me by others users"
+ "oracles-delegated-to-others": "Votes delegated by me to others users",
+ "oracles-delegated-to-me": "Votes delegated to me by others users"
},
"actions": {
"lock": {
"label": "Lock",
"title": "Lock {{currency}}",
- "description": "Lock {{currency}} to receive bv{{token}}",
- "get-amount-oracles": "Get {{amount}} bv{{token}}",
- "body": "You are locking /bepro{{amount}} {{currency}} /br/ to get /oracles{{oracleAmount}} bv{{token}}"
+ "description": "Lock {{currency}} to receive Votes",
+ "get-amount-oracles": "Get {{amount}} Votes",
+ "body": "You are locking /bepro{{amount}} {{currency}} /br/ to get /oracles{{oracleAmount}} Votes"
},
"unlock": {
"label": "Unlock",
"title": "Unlock {{currency}}",
- "description": "Get {{currency}} from bv{{token}}",
+ "description": "Get {{currency}} from Votes",
"get-amount-bepro": "Get {{amount}} {{currency}}",
- "body": "Give away /oracles{{amount}} bv{{token}}/ /br/ to get back /bepro{{oracleAmount}} {{currency}}"
+ "body": "Give away /oracles{{amount}} Votes/ /br/ to get back /bepro{{oracleAmount}} {{currency}}"
},
"delegate": {
"label": "Delegate",
- "title": "Delegate bv{{token}}",
- "delegate-to-address": "Delegate bv{{token}} to an address",
- "description": "Delegate bv{{token}} to help curators"
+ "title": "Delegate Votes",
+ "delegate-to-address": "Delegate Votes to an address",
+ "description": "Delegate Votes to help curators"
}
},
"fields": {
@@ -36,8 +36,8 @@
"placeholder": "Insert an amount of {{currency}}"
},
"oracles": {
- "label": "bv{{token}} Amount",
- "placeholder": "Insert an amount of bv{{token}}"
+ "label": "Votes Amount",
+ "placeholder": "Insert an amount of Votes"
},
"address": {
"label": "Delegation Address",
@@ -48,7 +48,7 @@
"amount-greater": "Amount is greater than your {{amount}} amount",
"amount-higher-0": "{{currency}} amount needs to be higher than 0.",
"fill-required-fields": "Please fill all required fields.",
- "self-delegate": "You can't delegate bv{{token}} to your own address.",
+ "self-delegate": "You can't delegate Votes to your own address.",
"approve-transactions": "Please approve {{currency}} Transactions First. Check it and try again.",
"no-delegates": "No delegations found",
"invalid-wallet": "Wallet Address Invalid."
diff --git a/public/locales/en/profile.json b/public/locales/en/profile.json
index 0fe9f94f5f..b5a9514ba8 100644
--- a/public/locales/en/profile.json
+++ b/public/locales/en/profile.json
@@ -1,13 +1,25 @@
{
"balance": "Balance",
+ "wallet": "Wallet",
+ "tokens": "Tokens",
+ "received-in-total": "Received in total",
"oracle-name-placeholder": "Locked Network Token",
"deletaged-to-me": "Delegated to me",
"deletaged-to-others": "Delegated to others",
+ "total-votes": "Total Votes",
+ "locked-by-me": "Locked by me",
"connect-wallet": "Connect Wallet",
"council": "Curator",
"connect-github": "Connect Github",
"go-to-network": "Go to Network",
"connections": "Connections",
+ "voting-power": "Voting Power",
+ "need-network-to-manage": "To manage your voting power you need to be in a especific network",
+ "network-columns": {
+ "network-name": "Network name",
+ "total-votes": "Total votes",
+ "network-link": "Network link"
+ },
"payments": {
"period": "Period"
},
diff --git a/public/locales/en/proposal.json b/public/locales/en/proposal.json
index 2e137119d1..6b973f6747 100644
--- a/public/locales/en/proposal.json
+++ b/public/locales/en/proposal.json
@@ -19,7 +19,9 @@
"no-proposals-created": "There are no proposals created.",
"distribution-cant-done": "This distribution can't be done try another one.",
"proposal-refused": "Proposal Refused",
- "in-disputable-time": "{{time}} before proposal can be merged."
+ "in-disputable-time": "{{time}} before proposal can be merged.",
+ "owner-pull-request": "You cannot accept a proposal containing your own pull request",
+ "owner-proposal": "You cannot accept a proposal created by you"
},
"errors": {
"not-found": "No proposals found",
diff --git a/scripts/deploy-multichain.js b/scripts/deploy-multichain.js
index fa20d35493..95c5fe49f4 100644
--- a/scripts/deploy-multichain.js
+++ b/scripts/deploy-multichain.js
@@ -42,10 +42,12 @@ const options = yargs(hideBin(process.argv))
async function main(option = 0) {
let chainData;
- if (_xNetworks[options.network[option]])
+ const isXNetwork = !!_xNetworks[options.network[option]];
+
+ if (isXNetwork)
chainData = _xNetworks[options.network[option]];
else chainData =
- await fetch(`https://chainid.network/chains_mini.json`)
+ await fetch(`https://chainid.network/chains.json`)
.then(d => d.json())
.then(data => data.find(d => d.networkId === +options.network[option]));
@@ -67,6 +69,7 @@ async function main(option = 0) {
DEPLOY_DRAFT_TIME = 60 * 5, // 5 minutes
DEPLOY_DISPUTABLE_TIME = 60 * 10, // 10 minutes
DEPLOY_COUNCIL_AMOUNT = 105000,
+ NEXT_PUBLIC_HOME_URL
} = env;
const connection = new Web3Connection({web3Host, privateKey});
@@ -183,7 +186,7 @@ async function main(option = 0) {
async function saveSettingsToDb({network, registry, payment, governance, reward, bounty}) {
console.debug("Saving settings to DB");
- const {chainTokenName, chainId, chainName, chainScan, eventsUrl,} = chainData;
+ const {chainTokenName, chainId, chainName, explorers, eventsUrl,} = chainData;
const {NEXT_PUBLIC_DEFAULT_NETWORK_NAME, NEXT_GH_OWNER, NEXT_GH_REPO} = env;
try {
@@ -195,6 +198,9 @@ async function main(option = 0) {
TokensModel.init(sequelize);
NetworkTokensModel.init(sequelize);
+ const chainScan = explorers?.length ? explorers[0].url : undefined;
+ const eventsApi = isXNetwork ? eventsUrl : `${NEXT_PUBLIC_HOME_URL}:2096`
+
await ChainModel.findOrCreate({
where: {
chainId: chainId
@@ -208,7 +214,7 @@ async function main(option = 0) {
chainCurrencySymbol: chainData?.nativeCurrency?.symbol || chainTokenName,
chainCurrencyDecimals: chainData?.nativeCurrency?.decimals || 18,
registryAddress: registry,
- eventsApi: eventsUrl,
+ eventsApi: eventsApi,
blockScanner: chainScan,
isDefault: false,
color: "#29b6af"
@@ -317,19 +323,21 @@ async function main(option = 0) {
return _token;
}
- const transfers = async ([payment, governance, rwd]) => {
- for (const address of accounts) {
+ /** Slice the BountyNFT from the saveTokens array and send transfers */
+ const [payment, governance, rwd] = await Promise.all(tokens.slice(0, 3).map(mapper));
+
+ for (const address of accounts) {
+ try {
console.debug(`Sending tokens to ${address}...`);
await payment.transferTokenAmount(address, 10000000);
await governance.transferTokenAmount(address, 10000000);
await rwd.transferTokenAmount(address, 10000000);
+ } catch (error) {
+ console.debug(`Failed to send tokens to ${address}`, error.toString());
}
-
- console.debug(`All tokens sent!`);
}
- /** Slice the BountyNFT from the saveTokens array and send transfers */
- await Promise.all(tokens.slice(0, 3).map(mapper)).then(transfers);
+ console.debug(`All tokens sent!`);
return tokens;
}
diff --git a/styles/styles.scss b/styles/styles.scss
index 56e6078d0a..6755f7787e 100644
--- a/styles/styles.scss
+++ b/styles/styles.scss
@@ -52,10 +52,10 @@
--bs-warning-rgb:#{toRGB($warning)};
--bs-secondary:#{$secondary};
--bs-secondary-rgb:#{toRGB($secondary)};
- --bs-body-bg:#{$gray-950};
- --bs-body-bg-rgb:#{toRGB($gray-950)};
- --bs-dark:#{$gray-950};
- --bs-dark-rgb:#{toRGB($gray-950)};
+ --bs-body-bg:#{$bg};
+ --bs-body-bg-rgb:#{toRGB($bg)};
+ --bs-dark:#{$bg};
+ --bs-dark-rgb:#{toRGB($bg)};
}
//bootstrap-overrides
@@ -226,7 +226,7 @@ li {
background-color: $gray-900;
z-index: 4;
padding: 6px;
-
+ margin-bottom: 50px;
&-list {
padding-top: 0;
padding-bottom: 0;
@@ -271,8 +271,6 @@ li {
}
}
-
-
// familys
.family-Regular {
font-family: "Space Grotesk", sans-serif;
@@ -574,14 +572,13 @@ label {
input[type="date"]::-webkit-calendar-picker-indicator {
- background-color: $white !important;
border-radius: 5px;
+ content: url(../assets/CalendarBlank.svg);
}
input[type="date"]::-webkit-calendar-picker-indicator:hover {
transform:scale(1.2);
cursor:pointer;
- background-color: rgba($white, 0.2);
}
.input-group-border {
@@ -713,7 +710,7 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover {
border: 1px solid $gray-700;
&.button-max {
padding: 0.90rem 1.25rem 0.75rem 1.25rem;
- }
+ }
&:hover {
border-radius: 4px;
border-color: $gray-700;
@@ -877,14 +874,22 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover {
font-weight: normal !important;
}
+.font-weight-500 {
+ font-weight: 500 !important;
+}
+
.font-weight-medium {
font-weight: 500 !important;
}
-.min-w-fit{
+.min-w-fit {
min-width: fit-content !important;
}
+.min-h-card {
+ min-height: 220px;
+}
+
.ico-metamask {
display: inline-block;
width: 18px;
@@ -1364,39 +1369,35 @@ a.row-button svg {
}
.my-network-tabs {
- border-radius: math.div($m, 2) math.div($m, 2) 0 0;
+ border: none;
+ border-bottom: 1px solid $gray-800;
+
+ .nav {
+ gap: 32px;
+ }
.nav-item {
+ width: fit-content;
+
.nav-link {
- font-family: "Space Grotesk", sans-serif;
- font-weight: 700;
- font-size: 16px;
- line-height: 160%;
- letter-spacing: 0.03em;
- text-transform: uppercase;
+ @extend .family-Regular;
+ font-weight: 500;
+ font-size: 18px;
+ line-height: 133%;
- border: 0;
- border-radius: math.div($m, 2) math.div($m, 2) 0 0;
- padding: 20px;
+ border: none;
+ padding: 20px 0;
- color: rgba($white, 0.4);
+ color: $gray-500;
+ span {
+ margin: 0;
+ }
&.active {
color: $white;
- background-color: $bg-shadow;
- }
- }
- }
-
- &.collapsed {
- border-radius: math.div($m, 2);
- .nav-item {
- &:first-child {
- .nav-link {
- border-bottom-left-radius: math.div($m, 2);
- }
+ border-bottom: 1px solid var(--bs-primary);
}
}
}
diff --git a/styles/variables.scss b/styles/variables.scss
index 553410641f..9bfa8db493 100644
--- a/styles/variables.scss
+++ b/styles/variables.scss
@@ -16,6 +16,7 @@ $light-warning: #CCAB38;
$dark-gray: #20222b;
$gray: #c4c7d3;
$gray-100: #E3E3E8;
+$gray-200: #C7C8D1;
$gray-150: #D5D6DC;
$gray-300: #ABACBA;
$gray-400: #8F91A3;
@@ -34,7 +35,7 @@ $disabled: #423b51;
$orange-500: #FF6A2C;
-$bg: #0d0f19;
+$bg: #0B0C0E;
$bg-opac: rgba($white, 0.1);
$bg-shadow: #151720;
$bg-blue-shadow: #1825ad;
@@ -84,6 +85,7 @@ $more-bg: (
"warning-30": rgba($warning, 0.3),
"gray-70": rgba($gray, 0.7),
"gray-100": $gray-100,
+ "gray-200": $gray-200,
"gray-150": $gray-150,
"gray-300": $gray-300,
"gray-400": $gray-400,
@@ -107,6 +109,7 @@ $more-colors: (
"purple": $purple,
"gray": $gray,
"gray-100": $gray-100,
+ "gray-200": $gray-200,
"gray-150": $gray-150,
"gray-300": $gray-300,
"gray-400": $gray-400,
diff --git a/x-hooks/use-api.tsx b/x-hooks/use-api.tsx
index f3bc3526d1..632d8b1947 100644
--- a/x-hooks/use-api.tsx
+++ b/x-hooks/use-api.tsx
@@ -34,7 +34,6 @@ import { Token } from "interfaces/token";
import {api} from "services/api";
import { WinStorage } from "services/win-storage";
-import {Entities, Events} from "types/dappkit";
import {updateSupportedChains} from "../contexts/reducers/change-supported-chains";
import {toastError, toastSuccess} from "../contexts/reducers/change-toaster";
@@ -158,7 +157,8 @@ export default function useApi() {
order = "DESC",
address = "",
creator = "",
- networkName = ""
+ networkName = "",
+ state = "open",
}) {
const params = new URLSearchParams({
address,
@@ -166,11 +166,15 @@ export default function useApi() {
sortBy,
order,
creator,
- networkName: networkName.replaceAll(" ", "-")
+ networkName: networkName.replaceAll(" ", "-"),
+ state
}).toString();
return api
.get(`/search/issues/recent/?${params}`)
- .then(({ data }): IssueBigNumberData[] => (data.map(issueParser)))
+ .then(({ data }): IssueBigNumberData[] => {
+ console.log(data.map(issue => ({type: typeof issue?.fundingAmount, value: issue?.fundingAmount})))
+ return (data.map(issueParser))
+ })
.catch((): IssueBigNumberData[] => ([]));
}
@@ -217,9 +221,9 @@ export default function useApi() {
.catch(() => null);
}
- async function getPayments(wallet: string, networkName = DEFAULT_NETWORK_NAME, startDate: string, endDate: string) {
+ async function getPayments(wallet: string, startDate: string, endDate: string) {
const dates = startDate ? { startDate, endDate } : { endDate }
- const params = new URLSearchParams({ wallet, networkName, ...dates }).toString();
+ const params = new URLSearchParams({ wallet, ...dates }).toString();
return api
.get(`/payments?${params}`)
@@ -597,10 +601,10 @@ export default function useApi() {
throw error;
});
}
-
- async function getTokens(chainId?: string) {
+
+ async function getTokens(chainId?: string, networkName?: string) {
return api
- .get("/search/tokens", { params: {chainId} })
+ .get("/search/tokens", { params: {chainId, networkName} })
.then(({ data }) => data)
.catch((error) => {
throw error;
@@ -703,10 +707,10 @@ export default function useApi() {
page = "1",
address = "",
isCurrentlyCurator = undefined,
- networkName = DEFAULT_NETWORK_NAME,
+ networkName = "",
sortBy = "updatedAt",
order = "DESC",
- chainShortName
+ chainShortName = ""
}: SearchCuratorParams) {
const params = new URLSearchParams({
page,