From 53fbf0629eae1118df446f85e58b0dd0d140f738 Mon Sep 17 00:00:00 2001 From: MoshMage Date: Tue, 14 Feb 2023 09:48:37 +0000 Subject: [PATCH 01/53] make tokens-settings.tsx also use useBepro handleChangeTokens and add a argument for add/remove --- .../my-network-settings/tokens-settings.tsx | 16 +++++----- components/setup/registry-setup.tsx | 30 +++++++++---------- services/dao-service.ts | 30 +++++++++---------- x-hooks/use-bepro.tsx | 9 ++++-- 4 files changed, 45 insertions(+), 40 deletions(-) diff --git a/components/profile/my-network-settings/tokens-settings.tsx b/components/profile/my-network-settings/tokens-settings.tsx index 38adb771d1..b67bae779a 100644 --- a/components/profile/my-network-settings/tokens-settings.tsx +++ b/components/profile/my-network-settings/tokens-settings.tsx @@ -3,10 +3,9 @@ import {Col, Row} from "react-bootstrap"; import {useTranslation} from "next-i18next"; -import { useNetworkSettings } from "contexts/network-settings"; +import {useNetworkSettings} from "contexts/network-settings"; -import {Token} from "interfaces/token"; -import {TokenType} from 'interfaces/token' +import {Token, TokenType} from "interfaces/token"; import useApi from "x-hooks/use-api"; @@ -14,6 +13,7 @@ import {useAppState} from "../../../contexts/app-state"; import Button from "../../button"; import MultipleTokensDropdown from "../../multiple-tokens-dropdown"; import {WarningSpan} from "../../warning-span"; +import useBepro from "../../../x-hooks/use-bepro"; interface SelectedTokens { [tokenType: TokenType | string]: string[] @@ -38,6 +38,7 @@ export default function TokensSettings({ const [allowedTransactionalTokensList, setAllowedTransactionalTokensList] = useState(); const { getTokens, processEvent } = useApi(); + const { handleChangeAllowedTokens } = useBepro(); const { fields @@ -130,17 +131,18 @@ export default function TokensSettings({ const selectedTokensAddress = selectedTokens.map(({address})=> address) const toAdd = selectedTokensAddress.filter((address)=> !currentTokens.includes(address)) - const toRemove = currentTokens.filter((address)=> !selectedTokensAddress.includes(address)) const transactions = [] - if(toAdd.length) transactions.push(state.Service?.active.addAllowedTokens(toAdd, isTransactional)) - if(toRemove.length) transactions.push(state.Service?.active.removeAllowedTokens(toRemove, isTransactional)) + if (toAdd.length) + transactions.push(handleChangeAllowedTokens(toAdd, isTransactional)) + if (toRemove.length) + transactions.push(handleChangeAllowedTokens(toRemove, isTransactional, false)) Promise.all(transactions).then(async (txs : { blockNumber: number }[]) => { const fromBlock = txs.reduce((acc, tx) => Math.min(acc, tx.blockNumber), Number.MAX_SAFE_INTEGER) - + await processEvent("registry", "changed", state.Service?.network?.active.name, { fromBlock }); await getAllowedTokensContract(); diff --git a/components/setup/registry-setup.tsx b/components/setup/registry-setup.tsx index 95f3f9653d..634737b02e 100644 --- a/components/setup/registry-setup.tsx +++ b/components/setup/registry-setup.tsx @@ -1,23 +1,23 @@ -import { useEffect, useState } from "react"; -import { Col, Row } from "react-bootstrap"; +import {useEffect, useState} from "react"; +import {Col, Row} from "react-bootstrap"; -import { TransactionReceipt } from "@taikai/dappkit/dist/src/interfaces/web3-core"; -import { useTranslation } from "next-i18next"; +import {TransactionReceipt} from "@taikai/dappkit/dist/src/interfaces/web3-core"; +import {useTranslation} from "next-i18next"; import Button from "components/button"; -import { ContextualSpan } from "components/contextual-span"; -import { FormGroup } from "components/form-group"; -import { CallToAction } from "components/setup/call-to-action"; -import { ContractField, ContractInput } from "components/setup/contract-input"; -import { DeployBountyTokenModal } from "components/setup/deploy-bounty-token-modal"; -import { DeployERC20Modal } from "components/setup/deploy-erc20-modal"; +import {ContextualSpan} from "components/contextual-span"; +import {FormGroup} from "components/form-group"; +import {CallToAction} from "components/setup/call-to-action"; +import {ContractField, ContractInput} from "components/setup/contract-input"; +import {DeployBountyTokenModal} from "components/setup/deploy-bounty-token-modal"; +import {DeployERC20Modal} from "components/setup/deploy-erc20-modal"; -import { useAppState } from "contexts/app-state"; -import { toastError, toastSuccess } from "contexts/reducers/change-toaster"; +import {useAppState} from "contexts/app-state"; +import {toastError, toastSuccess} from "contexts/reducers/change-toaster"; import useApi from "x-hooks/use-api"; import useBepro from "x-hooks/use-bepro"; -import { useSettings } from "x-hooks/use-settings"; +import {useSettings} from "x-hooks/use-settings"; interface RegistrySetupProps { isVisible?: boolean; @@ -63,7 +63,7 @@ export function RegistrySetup({ const { loadSettings } = useSettings(); const { saveNetworkRegistry, processEvent } = useApi(); const { dispatch, state: { currentUser, Service } } = useAppState(); - const { handleDeployRegistry, handleSetDispatcher, handleAddAllowedTokens } = useBepro(); + const { handleDeployRegistry, handleSetDispatcher, handleChangeAllowedTokens } = useBepro(); function isEmpty(value: string) { return value.trim() === ""; @@ -201,7 +201,7 @@ export function RegistrySetup({ } function allowToken(isTransactional: boolean) { - handleAddAllowedTokens([erc20.value], isTransactional) + handleChangeAllowedTokens([erc20.value], isTransactional) .then(txInfo => Promise.all([ updateData(), processEvent("registry", "changed", "", { fromBlock: (txInfo as { blockNumber: number }).blockNumber }) diff --git a/services/dao-service.ts b/services/dao-service.ts index 571fd4c1e5..e395d9284c 100644 --- a/services/dao-service.ts +++ b/services/dao-service.ts @@ -1,24 +1,24 @@ -import { - ERC20, +import { Bounty, + BountyToken, Defaults, + ERC20, Network_v2, - BountyToken, - TreasuryInfo, - Web3Connection, NetworkRegistry, - toSmartContractDecimals + toSmartContractDecimals, + TreasuryInfo, + Web3Connection } from "@taikai/dappkit"; -import { TransactionReceipt } from "@taikai/dappkit/dist/src/interfaces/web3-core"; +import {TransactionReceipt} from "@taikai/dappkit/dist/src/interfaces/web3-core"; import BigNumber from "bignumber.js"; import {PromiEvent, TransactionReceipt as TransactionReceiptWeb3Core} from "web3-core"; import {Contract} from "web3-eth-contract"; -import { BountyExtended } from "interfaces/bounty"; -import { OraclesResumeExtended } from "interfaces/oracles-state"; -import { Token } from "interfaces/token"; +import {BountyExtended} from "interfaces/bounty"; +import {OraclesResumeExtended} from "interfaces/oracles-state"; +import {Token} from "interfaces/token"; -import { NetworkParameters, RegistryParameters } from "types/dappkit"; +import {NetworkParameters, RegistryParameters} from "types/dappkit"; interface DAOServiceProps { skipWindowAssignment?: boolean; @@ -159,8 +159,12 @@ export default class DAO { const getTx = async (hash: string) => this.web3Connection.eth.getTransactionReceipt(hash); + const startTimeout = (hash: string) => + setTimeout(() => getTx(hash).then(handleTransaction), 1000); + // eslint-disable-next-line @typescript-eslint/no-explicit-any const handleTransaction = (tx: any) => { + debugger; if (!tx) { if (tries === maxTries) reject({ @@ -175,10 +179,6 @@ export default class DAO { } }; - const startTimeout = (hash: string) => - setTimeout(() => getTx(hash).then(handleTransaction), 1000); - - event.once(`transactionHash`, async (hash) => { try { _iban = hash; diff --git a/x-hooks/use-bepro.tsx b/x-hooks/use-bepro.tsx index 5318b3155f..065b481d3c 100644 --- a/x-hooks/use-bepro.tsx +++ b/x-hooks/use-bepro.tsx @@ -600,16 +600,19 @@ export default function useBepro() { }); } - async function handleAddAllowedTokens(addresses: string[], isTransactional: boolean) { + async function handleChangeAllowedTokens(addresses: string[], isTransactional: boolean, add = true) { return new Promise(async (resolve, reject) => { + const transaction = addTx([{ type: TransactionTypes.changeAllowedTokens, network: state.Service?.network?.active } as any]); + debugger; + dispatch(transaction); - await state.Service?.active.addAllowedTokens(addresses, isTransactional) + await state.Service?.active[( add ? 'addAllowedTokens' : 'removeAllowedTokens')](addresses, isTransactional) .then((txInfo: TransactionReceipt) => { dispatch(updateTx([parseTransaction(txInfo, transaction.payload[0] as SimpleBlockTransactionPayload)])); resolve(txInfo); @@ -663,7 +666,7 @@ export default function useBepro() { handleWithdrawFundRewardBounty, handleFeeSettings, handleDeployRegistry, - handleAddAllowedTokens, + handleChangeAllowedTokens, handleCloseNetwork, handleFeeNetworkCreation, handleAmountNetworkCreation From 63a5081277151e70c599d6385dd984683ec8a620 Mon Sep 17 00:00:00 2001 From: MoshMage Date: Tue, 14 Feb 2023 10:22:35 +0000 Subject: [PATCH 02/53] lint --fix --- components/profile/my-network-settings/tokens-settings.tsx | 2 +- services/dao-service.ts | 1 - x-hooks/use-bepro.tsx | 2 -- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/components/profile/my-network-settings/tokens-settings.tsx b/components/profile/my-network-settings/tokens-settings.tsx index b67bae779a..053f126ca7 100644 --- a/components/profile/my-network-settings/tokens-settings.tsx +++ b/components/profile/my-network-settings/tokens-settings.tsx @@ -10,10 +10,10 @@ import {Token, TokenType} from "interfaces/token"; import useApi from "x-hooks/use-api"; import {useAppState} from "../../../contexts/app-state"; +import useBepro from "../../../x-hooks/use-bepro"; import Button from "../../button"; import MultipleTokensDropdown from "../../multiple-tokens-dropdown"; import {WarningSpan} from "../../warning-span"; -import useBepro from "../../../x-hooks/use-bepro"; interface SelectedTokens { [tokenType: TokenType | string]: string[] diff --git a/services/dao-service.ts b/services/dao-service.ts index e395d9284c..5035e5e8c3 100644 --- a/services/dao-service.ts +++ b/services/dao-service.ts @@ -164,7 +164,6 @@ export default class DAO { // eslint-disable-next-line @typescript-eslint/no-explicit-any const handleTransaction = (tx: any) => { - debugger; if (!tx) { if (tries === maxTries) reject({ diff --git a/x-hooks/use-bepro.tsx b/x-hooks/use-bepro.tsx index 065b481d3c..3ede1323a0 100644 --- a/x-hooks/use-bepro.tsx +++ b/x-hooks/use-bepro.tsx @@ -608,8 +608,6 @@ export default function useBepro() { network: state.Service?.network?.active } as any]); - debugger; - dispatch(transaction); await state.Service?.active[( add ? 'addAllowedTokens' : 'removeAllowedTokens')](addresses, isTransactional) From 9cff83a5fdef591b0f6c7da189b8820cc007b65c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20Vin=C3=ADcius?= Date: Fri, 17 Feb 2023 12:07:42 -0300 Subject: [PATCH 03/53] Bepro 1418 after entering a funding request all bounties show as one (#870) * adding new if to fix funding section * fix if condition return getChainBounty * removing logic funding * adjusting spaces --- x-hooks/use-bounty.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/x-hooks/use-bounty.tsx b/x-hooks/use-bounty.tsx index 0cfe3beace..a476660ba5 100644 --- a/x-hooks/use-bounty.tsx +++ b/x-hooks/use-bounty.tsx @@ -120,7 +120,12 @@ export function useBounty() { function getChainBounty(force = false) { - if (!state.Service?.active?.network || !state.currentBounty?.data?.contractId || state.spinners?.bountyChain) + if ( + !state.Service?.active?.network || + !state.currentBounty?.data?.contractId || + state.spinners?.bountyChain || + query?.id !== state.currentBounty?.data?.githubId + ) return; dispatch(changeSpinners.update({bountyChain: true})) From f9291062d44762dfc58ee552cd371cfe43d89f99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20Vin=C3=ADcius?= Date: Fri, 17 Feb 2023 15:39:25 -0300 Subject: [PATCH 04/53] creating migration remove duplicated payments --- ...uplicated-payments-users-payments-table.js | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 db/migrations/2023021711570000-remove-duplicated-payments-users-payments-table.js diff --git a/db/migrations/2023021711570000-remove-duplicated-payments-users-payments-table.js b/db/migrations/2023021711570000-remove-duplicated-payments-users-payments-table.js new file mode 100644 index 0000000000..da609182c2 --- /dev/null +++ b/db/migrations/2023021711570000-remove-duplicated-payments-users-payments-table.js @@ -0,0 +1,43 @@ +"use strict"; + +const UsersPayments = require("../models/user-payments"); +const { Op } = require("sequelize"); +const name = "remove-duplicated-payments-users-payment-table"; + +module.exports = { + async up(queryInterface, Sequelize) { + console.log("start:", name); + + UsersPayments.init(queryInterface.sequelize); + + const Payments = await UsersPayments.findAll({}) + + const removedPayments = [] + for (const payment of Payments) { + if(!removedPayments.includes(payment.id)){ + const duplicatesPayments = await UsersPayments.findAll({ + where: { + address: payment.address, + ammount: payment.ammount, + issueId: payment.issueId, + transactionHash: payment.transactionHash + } + }) + + if(duplicatesPayments.length > 1){ + const needRemove = duplicatesPayments.map(({id}) => id).slice(1, duplicatesPayments.length) + await UsersPayments.destroy({ + where: { + id: { + [Op.in]: needRemove + } + }, + }) + needRemove.map(id => removedPayments.push(id)) + } + } + } + + console.log(`${name} - Removed duplications users payments - number of removals:${removedPayments.length}`); + }, +}; From da0488e0710b220bc34e48d70e69d4313bb0f6b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20Vin=C3=ADcius?= Date: Mon, 13 Feb 2023 11:52:29 -0300 Subject: [PATCH 05/53] creating new endpoint to edit bounty --- pages/api/issue/[...ids].ts | 87 ++++++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 5 deletions(-) diff --git a/pages/api/issue/[...ids].ts b/pages/api/issue/[...ids].ts index 9fea44eee0..028b74fbbc 100644 --- a/pages/api/issue/[...ids].ts +++ b/pages/api/issue/[...ids].ts @@ -1,9 +1,20 @@ +import { IssueRoute } from "middleware/issue-route"; import {NextApiRequest, NextApiResponse} from "next"; +import getConfig from "next/config"; +import { Octokit } from "octokit"; import {Op} from "sequelize"; import models from "db/models"; -import {LogAccess} from "../../../middleware/log-access"; -import WithCors from "../../../middleware/withCors"; + +import * as IssueQueries from "graphql/issue"; + +import { getPropertyRecursively } from "helpers/object"; + +import { GraphQlQueryResponseData, GraphQlResponse } from "types/octokit"; + +import {RouteMiddleware} from "../../../middleware"; + +const { serverRuntimeConfig } = getConfig(); async function get(req: NextApiRequest, res: NextApiResponse) { const { @@ -44,16 +55,82 @@ async function get(req: NextApiRequest, res: NextApiResponse) { return res.status(200).json(issue); } -export default LogAccess(WithCors(async function GetIssues(req: NextApiRequest, - res: NextApiResponse) { +async function put(req: NextApiRequest, res: NextApiResponse) { + const { + ids: [repoId, ghId, networkName], + } = req.query; + + const { + body, + tags + } = req.body; + + const issueId = [repoId, ghId].join("/"); + + const network = await models.network.findOne({ + where: { + name: { + [Op.iLike]: String(networkName).replaceAll(" ", "-") + } + } + }); + + if (!network) return res.status(404).json({message:"Invalid network"}); + + const issue = await models.issue.findOne({ + where: { + issueId, + network_id: network?.id + }, + include: [{ association: "repository" }] + }); + + if (!issue) return res.status(404).json({message: "bounty not found"}); + + if(issue.state === 'draft'){ + if(body) issue.body = body + if(tags) issue.tags = tags + await issue.save() + + const [owner, repo] = issue.repository.githubPath.split("/"); + + const githubAPI = (new Octokit({ auth: serverRuntimeConfig?.github?.token })).graphql; + + const issueDetails = await githubAPI(IssueQueries.Details, { + repo, + owner, + issueId: +issue.githubId + }); + + const issueGithubId = issueDetails.repository.issue.id; + + const updateIssue = getPropertyRecursively("node", + await githubAPI(IssueQueries.Update, { + body: body, + issueId: issueGithubId, + })); + + return res.status(200).json(updateIssue); + } else{ + return res.status(400).json({message: 'bounty not in draft'}) + } +} + +async function IssuesMethods(req: NextApiRequest, + res: NextApiResponse) { switch (req.method.toLowerCase()) { case "get": await get(req, res); break; + case "put": + await put(req, res); + break; default: res.status(405).json("Method not allowed"); } res.end(); -})) +} + +export default IssueRoute(RouteMiddleware(IssuesMethods)) From 34658af8be0733eda2f9bc8ed39d65ef67e90adb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20Vin=C3=ADcius?= Date: Mon, 13 Feb 2023 11:52:55 -0300 Subject: [PATCH 06/53] creating new interface updateIssueParams --- interfaces/api.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/interfaces/api.ts b/interfaces/api.ts index 70ac8d0b0d..9768bb19f3 100644 --- a/interfaces/api.ts +++ b/interfaces/api.ts @@ -87,4 +87,12 @@ export interface PatchUserParams extends RequestParams { githubLogin: string; migrate?: boolean; reset?: boolean; +} + +export interface updateIssueParams extends RequestParams { + repoId: string | number; + ghId: string | number; + networkName: string; + body?: string; + tags?: string[]; } \ No newline at end of file From e03f3dd32402f02f857848275f27b46f619b1dd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20Vin=C3=ADcius?= Date: Mon, 13 Feb 2023 11:53:45 -0300 Subject: [PATCH 07/53] initial structure to edit description --- components/issue-description.tsx | 36 +++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/components/issue-description.tsx b/components/issue-description.tsx index e8eaf4c8f8..6fe2f80b47 100644 --- a/components/issue-description.tsx +++ b/components/issue-description.tsx @@ -1,18 +1,44 @@ +import React, { useEffect, useState } from "react"; + import { useTranslation } from "next-i18next"; import MarkedRender from "components/MarkedRender"; -export default function IssueDescription({ description }) { - const { t } = useTranslation("common"); +interface DescriptionProps { description: string; isEdit?: boolean} + +export default function IssueDescription({ description, isEdit = false }: DescriptionProps) { + const { t } = useTranslation(["common", "bounty"]); + const [body, setBody] = useState(); + + useEffect(() => { + setBody(description) + },[description]) + + + function handleChangeBody(e: React.ChangeEvent) { + setBody(e.target.value) + } return ( -
+ <>

{t("misc.description")}

- + {isEdit ? ( +