From bbf9acf5ef7a1d89adbcc1d8a8deb67c338cb579 Mon Sep 17 00:00:00 2001 From: Doug Kent Date: Wed, 30 Sep 2020 13:24:09 -0400 Subject: [PATCH 1/4] introduce polling (#2151) * Introduce polling, fix a couple of bugs * lint * peg arc.js version * poll for boosted proposals * delete spaces --- package-lock.json | 13 +--- package.json | 2 +- src/components/Account/AccountBalances.tsx | 4 +- src/components/Account/AccountProfilePage.tsx | 4 +- src/components/Dao/DaoContainer.tsx | 3 +- src/components/Dao/DaoHistoryPage.tsx | 3 +- src/components/Dao/DaoSchemesPage.tsx | 3 +- src/components/Dao/ProposalSchemeCard.tsx | 9 +-- src/components/Daos/DaosPage.tsx | 20 +++--- .../Create/SchemeForms/TagsSelector.tsx | 2 +- src/components/Proposal/ProposalData.tsx | 14 ++-- .../Proposal/ProposalDetailsPage.tsx | 2 +- .../Proposal/Voting/VotersModal.tsx | 4 +- .../Redemptions/RedemptionsButton.tsx | 9 +-- .../Redemptions/RedemptionsMenu.tsx | 14 ++-- .../Redemptions/RedemptionsPage.tsx | 12 ++-- .../Competition/Details.tsx | 69 ++++++++++--------- .../Competition/List.tsx | 7 +- .../Competition/utils.ts | 35 ++++++---- .../DetailsPageRouter.tsx | 15 ++-- src/components/Scheme/SchemeContainer.tsx | 31 +++++---- src/components/Scheme/SchemeProposalsPage.tsx | 25 +++---- src/layouts/Header.tsx | 27 ++++---- src/layouts/SidebarMenu.tsx | 19 +++-- src/lib/util.ts | 4 ++ src/settings.ts | 1 + 26 files changed, 180 insertions(+), 171 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9cf3b0df1..06e3ed813 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1829,9 +1829,9 @@ } }, "@daostack/arc.js": { - "version": "0.2.73", - "resolved": "https://registry.npmjs.org/@daostack/arc.js/-/arc.js-0.2.73.tgz", - "integrity": "sha512-9YWtvE/29f+wW3NnyVv1YHYSGkts0yKLR2oeDmEShno5jKcTdBlhK/ZJaauW4wWPHcWAowKZ7ZOW5ea/BxP+SQ==", + "version": "0.2.74", + "resolved": "https://registry.npmjs.org/@daostack/arc.js/-/arc.js-0.2.74.tgz", + "integrity": "sha512-M3DbrmqUSYh+BlEPiuhaI1A+HZRwwjL2O/zEVOukPaxjlvImzMuKFAiH4DaXmOjlOkNrl+LJevvHc8J+3n5dAg==", "requires": { "apollo-cache-inmemory": "^1.6.5", "apollo-client": "^2.6.8", @@ -7344,13 +7344,6 @@ "requires": { "@types/node": ">=6", "tslib": "^1.9.3" - }, - "dependencies": { - "@types/node": { - "version": "14.10.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.10.1.tgz", - "integrity": "sha512-aYNbO+FZ/3KGeQCEkNhHFRIzBOUgc7QvcVNKXbfnhDkSfwUv91JsQQa10rDgKSTSLkXZ1UIyPe4FJJNVgw1xWQ==" - } } }, "@wry/equality": { diff --git a/package.json b/package.json index acdb5e66c..5881138dd 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "dependencies": { "3box": "1.17.1", "@burner-wallet/burner-connect-provider": "^0.1.1", - "@daostack/arc.js": "0.2.73", + "@daostack/arc.js": "0.2.74", "@dorgtech/daocreator-ui": "^1.0.13", "@fortawesome/fontawesome-svg-core": "^1.2.10", "@fortawesome/free-brands-svg-icons": "^5.6.1", diff --git a/src/components/Account/AccountBalances.tsx b/src/components/Account/AccountBalances.tsx index fe8f285e3..adc48fad3 100644 --- a/src/components/Account/AccountBalances.tsx +++ b/src/components/Account/AccountBalances.tsx @@ -1,5 +1,5 @@ import { Address, IDAOState, IMemberState } from "@daostack/arc.js"; -import { baseTokenName, ethErrorHandler, genName, ethBalance } from "lib/util"; +import { baseTokenName, ethErrorHandler, genName, ethBalance, standardPolling } from "lib/util"; import BN = require("bn.js"); import AccountBalance from "components/Account/AccountBalance"; @@ -69,7 +69,7 @@ export default withSubscription({ return combineLatest( address, - (address && dao && dao.dao.member(address).state( { subscribe: true })) || of(null), + (address && dao && dao.dao.member(address).state( standardPolling())) || of(null), ethBalance(address).pipe(ethErrorHandler()), arc.GENToken().balanceOf(address).pipe(ethErrorHandler()), ); diff --git a/src/components/Account/AccountProfilePage.tsx b/src/components/Account/AccountProfilePage.tsx index 5a1a05afb..57f5a001d 100644 --- a/src/components/Account/AccountProfilePage.tsx +++ b/src/components/Account/AccountProfilePage.tsx @@ -12,7 +12,7 @@ import ThreeboxModal from "components/Shared/ThreeboxModal"; import withSubscription, { ISubscriptionProps } from "components/Shared/withSubscription"; import { Field, Formik, FormikProps } from "formik"; import Analytics from "lib/analytics"; -import { baseTokenName, ethErrorHandler, genName, formatTokens, ethBalance } from "lib/util"; +import { baseTokenName, ethErrorHandler, genName, formatTokens, ethBalance, standardPolling } from "lib/util"; import CopyToClipboard, { IconColor } from "components/Shared/CopyToClipboard"; import { Page } from "pages"; import { parse } from "query-string"; @@ -329,7 +329,7 @@ const SubscribedAccountProfilePage = withSubscription({ return combineLatest( // subscribe if only to to get DAO reputation supply updates - daoAvatarAddress ? dao.state( {subscribe: true}) : of(null), + daoAvatarAddress ? dao.state( standardPolling()) : of(null), daoAvatarAddress ? dao.member(accountAddress).state() : of(null), ethBalance(accountAddress) .pipe(ethErrorHandler()), diff --git a/src/components/Dao/DaoContainer.tsx b/src/components/Dao/DaoContainer.tsx index 0940067c6..9486817df 100644 --- a/src/components/Dao/DaoContainer.tsx +++ b/src/components/Dao/DaoContainer.tsx @@ -23,6 +23,7 @@ import DaoHistoryPage from "./DaoHistoryPage"; import DaoMembersPage from "./DaoMembersPage"; import * as css from "./Dao.scss"; import DaoLandingPage from "components/Dao/DaoLandingPage"; +import { standardPolling } from "lib/util"; type IExternalProps = RouteComponentProps; @@ -151,7 +152,7 @@ const SubscribedDaoContainer = withSubscription({ const daoAddress = props.match.params.daoAvatarAddress; const dao = arc.dao(daoAddress); const observable = combineLatest( - dao.state({ subscribe: true, fetchAllData: true }), // DAO state + dao.state(standardPolling(true)), // DAO state dao.members() ); return observable; diff --git a/src/components/Dao/DaoHistoryPage.tsx b/src/components/Dao/DaoHistoryPage.tsx index 17a5b4939..eb1fdbbc1 100644 --- a/src/components/Dao/DaoHistoryPage.tsx +++ b/src/components/Dao/DaoHistoryPage.tsx @@ -13,6 +13,7 @@ import { first } from "rxjs/operators"; import ProposalHistoryRow from "../Proposal/ProposalHistoryRow"; import * as css from "./DaoHistoryPage.scss"; import { Observable } from "rxjs"; +import { standardPolling } from "lib/util"; const PAGE_SIZE = 50; @@ -209,7 +210,7 @@ export default withSubscription({ ${Scheme.fragments.SchemeFields} `; - await arc.getObservable(prefetchQuery, { subscribe: true }).pipe(first()).toPromise(); + await arc.getObservable(prefetchQuery, standardPolling()).pipe(first()).toPromise(); return proposalsQuery(dao, 0); }, diff --git a/src/components/Dao/DaoSchemesPage.tsx b/src/components/Dao/DaoSchemesPage.tsx index 9227caedb..7ca568638 100644 --- a/src/components/Dao/DaoSchemesPage.tsx +++ b/src/components/Dao/DaoSchemesPage.tsx @@ -20,6 +20,7 @@ import { mergeMap } from "rxjs/operators"; import * as css from "./DaoSchemesPage.scss"; import ProposalSchemeCard from "./ProposalSchemeCard"; import SimpleSchemeCard from "./SimpleSchemeCard"; +import { standardPolling } from "lib/util"; const Fade = ({ children, ...props }: any) => ( ): Observable => scheme[0] ? scheme[0].state() : of(null))) ); diff --git a/src/components/Dao/ProposalSchemeCard.tsx b/src/components/Dao/ProposalSchemeCard.tsx index 87db817d4..39f93c0f2 100644 --- a/src/components/Dao/ProposalSchemeCard.tsx +++ b/src/components/Dao/ProposalSchemeCard.tsx @@ -4,7 +4,7 @@ import VoteGraph from "components/Proposal/Voting/VoteGraph"; import ProposalCountdown from "components/Shared/ProposalCountdown"; import Loading from "components/Shared/Loading"; import withSubscription, { ISubscriptionProps } from "components/Shared/withSubscription"; -import { humanProposalTitle } from "lib/util"; +import { humanProposalTitle, standardPolling } from "lib/util"; import { schemeName } from "lib/schemeUtils"; import * as React from "react"; import { Link } from "react-router-dom"; @@ -91,17 +91,14 @@ export default withSubscription({ const arc = getArc(); const dao = arc.dao(props.dao.address); return combineLatest( - props.scheme.state(), + props.scheme.state(standardPolling()), dao.proposals({ where: { scheme: props.scheme.id, // eslint-disable-next-line @typescript-eslint/camelcase stage_in: [IProposalStage.Boosted, IProposalStage.QuietEndingPeriod], }, orderBy: "boostedAt", - }, { - fetchAllData: true, - subscribe: true, // subscribe to updates of the proposals. We can replace this once https://github.com/daostack/subgraph/issues/326 is done - }) // the list of boosted proposals + }, standardPolling(true)) // the list of boosted proposals ); }, }); diff --git a/src/components/Daos/DaosPage.tsx b/src/components/Daos/DaosPage.tsx index 548f28b74..a7424882f 100644 --- a/src/components/Daos/DaosPage.tsx +++ b/src/components/Daos/DaosPage.tsx @@ -15,7 +15,7 @@ import { IRootState } from "reducers"; import { combineLatest, of } from "rxjs"; import { first } from "rxjs/operators"; import cn from "classnames"; -import { showSimpleMessage } from "lib/util"; +import { showSimpleMessage, standardPolling } from "lib/util"; import DaoCard from "./DaoCard"; import * as css from "./Daos.scss"; import BHubReg from "../Buidlhub/Registration"; @@ -136,8 +136,8 @@ class DaosPage extends React.Component { // Otherwise show registered DAOs otherDAOs = otherDAOs.filter((d: DAO) => { return !yourDAOAddresses.includes(d.id) && - d.staticState.name.toLowerCase().includes(search) && - d.staticState.register === "registered"; + d.staticState.name.toLowerCase().includes(search) && + d.staticState.register === "registered"; }); } @@ -184,8 +184,8 @@ class DaosPage extends React.Component {

Your DAOs {process.env.NETWORK !== "xdai" ? - - : "" } + + : ""}

@@ -245,12 +245,12 @@ const createSubscriptionObservable = (props: IStateProps, data: SubscriptionData } ${DAOFieldsFragment} `; - const memberOfDAOs = currentAccountAddress ? arc.getObservableList(memberDAOsquery, (r: any) => createDaoStateFromQuery(r.dao).dao, { subscribe: true }) : of([]); + const memberOfDAOs = currentAccountAddress ? arc.getObservableList(memberDAOsquery, (r: any) => createDaoStateFromQuery(r.dao).dao, standardPolling()) : of([]); // eslint-disable-next-line @typescript-eslint/camelcase - const followDAOs = followingDAOs.length ? arc.daos({ where: { id_in: followingDAOs }, orderBy: "name", orderDirection: "asc"}, { fetchAllData: true, subscribe: true }) : of([]); + const followDAOs = followingDAOs.length ? arc.daos({ where: { id_in: followingDAOs }, orderBy: "name", orderDirection: "asc" }, standardPolling(true)) : of([]); return combineLatest( - arc.daos({ orderBy: "name", orderDirection: "asc", first: PAGE_SIZE, skip: data ? data[0].length : 0}, { fetchAllData: true, subscribe: true }), + arc.daos({ orderBy: "name", orderDirection: "asc", first: PAGE_SIZE, skip: data ? data[0].length : 0 }, standardPolling(true)), followDAOs, memberOfDAOs ); @@ -258,8 +258,8 @@ const createSubscriptionObservable = (props: IStateProps, data: SubscriptionData const SubscribedDaosPage = withSubscription({ wrappedComponent: DaosPage, - loadingComponent:
, - errorComponent: (props) =>
{ props.error.message }
, + loadingComponent:
, + errorComponent: (props) =>
{props.error.message}
, // Don't ever update the subscription checkForUpdate: ["currentAccountAddress", "followingDAOs"], diff --git a/src/components/Proposal/Create/SchemeForms/TagsSelector.tsx b/src/components/Proposal/Create/SchemeForms/TagsSelector.tsx index 8c29d0e1b..c9a299ade 100644 --- a/src/components/Proposal/Create/SchemeForms/TagsSelector.tsx +++ b/src/components/Proposal/Create/SchemeForms/TagsSelector.tsx @@ -163,7 +163,7 @@ export default withSubscription({ * Returns an array of ITagState. * Ask for `first: 1000` to raise the minimum from the default of 100 to the max of 1000 */ - return arc.tags({ first: 1000 }, { subscribe: false }) + return arc.tags({ first: 1000 }, { }) .pipe( map((tags: Array) => tags.map(tag => tag.staticState)) ); diff --git a/src/components/Proposal/ProposalData.tsx b/src/components/Proposal/ProposalData.tsx index dd55353ef..71460c84a 100644 --- a/src/components/Proposal/ProposalData.tsx +++ b/src/components/Proposal/ProposalData.tsx @@ -1,6 +1,6 @@ import { Address, IDAOState, IMemberState, IProposalState, IRewardState, Reward, Stake, Vote } from "@daostack/arc.js"; import { getArc } from "arc"; -import { ethErrorHandler, ethBalance } from "lib/util"; +import { ethErrorHandler, ethBalance, standardPolling } from "lib/util"; import BN = require("bn.js"); import withSubscription, { ISubscriptionProps } from "components/Shared/withSubscription"; @@ -20,10 +20,6 @@ interface IExternalProps { daoState: IDAOState; proposalId: string; children(props: IInjectedProposalProps): JSX.Element; - /** - * true to subscribe to changes in votes, stakes and rewards - */ - subscribeToProposalDetails?: boolean; } interface IStateProps { @@ -129,10 +125,10 @@ export default withSubscription({ if (currentAccountAddress) { return combineLatest( - proposal.state({ subscribe: props.subscribeToProposalDetails }), // state of the current proposal - proposal.votes({where: { voter: currentAccountAddress }}, { subscribe: props.subscribeToProposalDetails }), - proposal.stakes({where: { staker: currentAccountAddress }}, { subscribe: props.subscribeToProposalDetails }), - proposal.rewards({ where: {beneficiary: currentAccountAddress}}, { subscribe: props.subscribeToProposalDetails }) + proposal.state(standardPolling()), // state of the current proposal + proposal.votes({where: { voter: currentAccountAddress }}, standardPolling()), + proposal.stakes({where: { staker: currentAccountAddress }}, standardPolling()), + proposal.rewards({ where: {beneficiary: currentAccountAddress}}, standardPolling()) .pipe(map((rewards: Reward[]): Reward => rewards.length === 1 && rewards[0] || null)) .pipe(mergeMap(((reward: Reward): Observable => reward ? reward.state() : of(null)))), diff --git a/src/components/Proposal/ProposalDetailsPage.tsx b/src/components/Proposal/ProposalDetailsPage.tsx index e006aca90..94d22c70b 100644 --- a/src/components/Proposal/ProposalDetailsPage.tsx +++ b/src/components/Proposal/ProposalDetailsPage.tsx @@ -346,7 +346,7 @@ class ProposalDetailsPage extends React.Component { export default function ProposalDetailsPageData(props: IExternalProps) { const { currentAccountAddress, daoState, proposalId } = props; - return + return {proposalData => } ; } diff --git a/src/components/Proposal/Voting/VotersModal.tsx b/src/components/Proposal/Voting/VotersModal.tsx index 8cb4b0a21..73c0ced1a 100644 --- a/src/components/Proposal/Voting/VotersModal.tsx +++ b/src/components/Proposal/Voting/VotersModal.tsx @@ -191,8 +191,8 @@ const voterModalWithSubscriptions = withSubscription({ const dao = arc.dao(props.dao.address); const proposalId = props.proposal.id; const proposal = dao.proposal(proposalId); - - return proposal.votes({}, { subscribe: false }); + // subscribe is false by default + return proposal.votes({}, { }); }, }); diff --git a/src/components/Redemptions/RedemptionsButton.tsx b/src/components/Redemptions/RedemptionsButton.tsx index d10cad79d..395fd5591 100644 --- a/src/components/Redemptions/RedemptionsButton.tsx +++ b/src/components/Redemptions/RedemptionsButton.tsx @@ -9,6 +9,7 @@ import { of } from "rxjs"; import { map } from "rxjs/operators"; import RedemptionsMenu from "./RedemptionsMenu"; import * as css from "./RedemptionsButton.scss"; +import { standardPolling } from "lib/util"; interface IExternalProps { currentAccountAddress?: Address; @@ -27,7 +28,7 @@ class RedemptionsButton extends React.Component { } return
- { document.documentElement.clientWidth < 640 ? + {document.documentElement.clientWidth < 640 ? this.renderDirectLink() : this.renderQuickMenuLink() } @@ -38,7 +39,7 @@ class RedemptionsButton extends React.Component { const { data: redeemableProposals } = this.props; return - { redeemableProposals.length > 0 ? + {redeemableProposals.length > 0 ? : ""} ; @@ -63,7 +64,7 @@ class RedemptionsButton extends React.Component { >
- { redeemableProposals.length > 0 ? + {redeemableProposals.length > 0 ? : ""}
@@ -96,7 +97,7 @@ export default withSubscription({ id } }`; - return arc.getObservable(redeemableProposalsQuery, { subscribe: true }) + return arc.getObservable(redeemableProposalsQuery, standardPolling()) .pipe(map((result: any) => result.data.proposals)); }, }); diff --git a/src/components/Redemptions/RedemptionsMenu.tsx b/src/components/Redemptions/RedemptionsMenu.tsx index 4c93ed5ce..bd2bd21bc 100644 --- a/src/components/Redemptions/RedemptionsMenu.tsx +++ b/src/components/Redemptions/RedemptionsMenu.tsx @@ -7,7 +7,7 @@ import withSubscription, { ISubscriptionProps } from "components/Shared/withSubs import ActionButton from "components/Proposal/ActionButton"; import RedemptionsString from "components/Proposal/RedemptionsString"; import ProposalSummary from "components/Proposal/ProposalSummary"; -import { ethErrorHandler, humanProposalTitle, ethBalance } from "lib/util"; +import { ethErrorHandler, humanProposalTitle, ethBalance, standardPolling } from "lib/util"; import { Page } from "pages"; import * as React from "react"; import { connect } from "react-redux"; @@ -63,7 +63,7 @@ class RedemptionsMenu extends React.Component { )) :

Nothing to redeem

- +
}
@@ -106,7 +106,7 @@ class RedemptionsMenu extends React.Component { const SubscribedRedemptionsMenu = withSubscription({ wrappedComponent: RedemptionsMenu, loadingComponent:
Loading...
, - errorComponent: (props) =>
{ props.error.message }
, + errorComponent: (props) =>
{props.error.message}
, checkForUpdate: ["redeemableProposals"], createObservable: (props: IExternalProps) => { const arc = getArc(); @@ -151,7 +151,7 @@ const mapStateToItemContentProps = (state: IRootState, ownProps: IMenuItemProps) }; }; -type IMenuItemContentProps = IMenuItemProps & IMenuItemContentStateProps & ISubscriptionProps<[IDAOState, BN|null, IRewardState]>; +type IMenuItemContentProps = IMenuItemProps & IMenuItemContentStateProps & ISubscriptionProps<[IDAOState, BN | null, IRewardState]>; class MenuItemContent extends React.Component { public render(): RenderOutput { @@ -192,18 +192,18 @@ class MenuItemContent extends React.Component { const SubscribedMenuItemContent = withSubscription({ wrappedComponent: MenuItemContent, loadingComponent:
Loading...
, - errorComponent: (props) =>
{ props.error.message }
, + errorComponent: (props) =>
{props.error.message}
, checkForUpdate: [], // Parent component will rerender anyway. createObservable: (props: IMenuItemProps) => { const { currentAccountAddress, proposal } = props; const arc = getArc(); const dao = arc.dao(proposal.dao.id); const daoEthBalance = concat(of(new BN("0")), ethBalance(proposal.dao.id)).pipe(ethErrorHandler()); - const rewards = proposal.proposal.rewards({ where: { beneficiary: currentAccountAddress }}) + const rewards = proposal.proposal.rewards({ where: { beneficiary: currentAccountAddress } }) .pipe(map((rewards: Reward[]): Reward => rewards.length === 1 && rewards[0] || null)) .pipe(mergeMap(((reward: Reward): Observable => reward ? reward.state() : of(null)))); // subscribe to dao to get DAO reputation supply updates - return combineLatest(dao.state( { subscribe: true }), daoEthBalance, rewards); + return combineLatest(dao.state(standardPolling()), daoEthBalance, rewards); }, }); diff --git a/src/components/Redemptions/RedemptionsPage.tsx b/src/components/Redemptions/RedemptionsPage.tsx index b5e7f8fc3..eb34f2510 100644 --- a/src/components/Redemptions/RedemptionsPage.tsx +++ b/src/components/Redemptions/RedemptionsPage.tsx @@ -8,7 +8,7 @@ import withSubscription, { ISubscriptionProps } from "components/Shared/withSubs import gql from "graphql-tag"; import Analytics from "lib/analytics"; import { createDaoStateFromQuery, IDAOData } from "lib/daoHelpers"; -import { baseTokenName, formatTokens, genName, tokenDecimals, tokenSymbol } from "lib/util"; +import { baseTokenName, formatTokens, genName, standardPolling, tokenDecimals, tokenSymbol } from "lib/util"; import { Page } from "pages"; import * as React from "react"; import { BreadcrumbsItem } from "react-breadcrumbs-dynamic"; @@ -101,7 +101,7 @@ class RedemptionsPage extends React.Component {
{this.renderProposalsPerDAO()}
:
- +

Nothing to redeem

Get more rewards by proposing a proposal that the DAO accepts, and by voting / staking in alignment with the DAO.

@@ -180,7 +180,7 @@ class RedemptionsPage extends React.Component { genReward.iadd(new BN(reward.daoBountyForStaker)); } if ((reward.reputationForVoter && Number(reward.reputationForVoterRedeemedAt) === 0) - || (reward.reputationForProposer && Number(reward.reputationForProposerRedeemedAt) === 0)) { + || (reward.reputationForProposer && Number(reward.reputationForProposerRedeemedAt) === 0)) { reputationRewardDaos.add(proposal.dao.id); } } @@ -230,8 +230,8 @@ class RedemptionsPage extends React.Component { const SubscribedRedemptionsPage = withSubscription({ wrappedComponent: RedemptionsPage, - loadingComponent: , - errorComponent: (props) =>
{ props.error.message }
, + loadingComponent: , + errorComponent: (props) =>
{props.error.message}
, checkForUpdate: ["currentAccountAddress"], createObservable: (props: IStateProps) => { const { currentAccountAddress } = props; @@ -276,7 +276,7 @@ const SubscribedRedemptionsPage = withSubscription({ } ${DAOFieldsFragment} `; - const proposals = arc.getObservable(query, { subscribe: true }) + const proposals = arc.getObservable(query, standardPolling()) .pipe(map((result: any) => result.data.proposals)); return proposals; }, diff --git a/src/components/Scheme/ContributionRewardExtRewarders/Competition/Details.tsx b/src/components/Scheme/ContributionRewardExtRewarders/Competition/Details.tsx index f6ddf4f01..f876c3ade 100644 --- a/src/components/Scheme/ContributionRewardExtRewarders/Competition/Details.tsx +++ b/src/components/Scheme/ContributionRewardExtRewarders/Competition/Details.tsx @@ -18,8 +18,10 @@ import classNames from "classnames"; import { Link, RouteComponentProps } from "react-router-dom"; import { DiscussionEmbed } from "disqus-react"; import { connect } from "react-redux"; -import { IDAOState, IProposalState, ICompetitionSuggestionState, Address, CompetitionVote, IProposalOutcome, - CompetitionSuggestion, Proposal, Scheme } from "@daostack/arc.js"; +import { + IDAOState, IProposalState, ICompetitionSuggestionState, Address, CompetitionVote, IProposalOutcome, + CompetitionSuggestion, Proposal, Scheme, +} from "@daostack/arc.js"; import gql from "graphql-tag"; import { BreadcrumbsItem } from "react-breadcrumbs-dynamic"; import * as React from "react"; @@ -180,7 +182,7 @@ class CompetitionDetails extends React.Component { private distributionsHtml() { return this.props.proposalState.competition.rewardSplit.map((split: number, index: number) => { return (
-
{index+1}
+
{index + 1}
{split}%
); }); @@ -215,23 +217,24 @@ class CompetitionDetails extends React.Component {
{submission.isWinner ? : ""} -
: "" } -
: ""} +
- { submission.title || "[No title is available]" } + {submission.title || "[No title is available]"}
-
- +
-
+
- { formatTokens(submission.totalVotes) } Rep{/**/ } + {formatTokens(submission.totalVotes)} Rep{/**/}
@@ -263,10 +266,10 @@ class CompetitionDetails extends React.Component { const hasSubmissions = !!numSubmissions; const submissionsAreDisabled = notStarted || - // note that winningOutcome is the *current* state, not necessarily the *final* outcome - (!proposalState.executedAt || (proposalState.winningOutcome !== IProposalOutcome.Pass)) - || (isAddress(competition.admin) && (this.props.currentAccountAddress !== competition.admin)) - ; + // note that winningOutcome is the *current* state, not necessarily the *final* outcome + (!proposalState.executedAt || (proposalState.winningOutcome !== IProposalOutcome.Pass)) + || (isAddress(competition.admin) && (this.props.currentAccountAddress !== competition.admin)) + ; this.disqusConfig.title = proposalState.title; this.disqusConfig.url = process.env.BASE_URL + this.props.history.location.pathname; @@ -282,7 +285,7 @@ class CompetitionDetails extends React.Component { - { hasSubmissions ? + {hasSubmissions ?
{numSubmissions} Submissions
-
+
{this.submissionsHtml()}
: "" } - { ((inVoting && !voting) || (isOver && !overWithWinners)) ? this.noWinnersHtml() : "" } + {((inVoting && !voting) || (isOver && !overWithWinners)) ? this.noWinnersHtml() : ""}
Discussion
- +
@@ -392,12 +395,12 @@ class CompetitionDetails extends React.Component {
{ props.error.message }
, + errorComponent: (props) =>
{props.error.message}
, checkForUpdate: ["currentAccountAddress"], - createObservable: async (props: IExternalProps & IExternalStateProps ) => { + createObservable: async (props: IExternalProps & IExternalStateProps) => { // prime the cache and subscribe const cacheQuery = gql`query cacheSuggestions { @@ -442,7 +445,7 @@ export default withSubscription({ // // sending the query before subscribing seems to resolve a weird cache error - this would ideally be handled in the client // await arc.sendQuery(cacheQuery); // // eslint-disable-next-line @typescript-eslint/no-empty-function - // await arc.getObservable(cacheQuery, {subscribe: true}).subscribe(() => {}); + // await arc.getObservable(cacheQuery, standardPolling()).subscribe(() => {}); // end cache priming return combineLatest( diff --git a/src/components/Scheme/ContributionRewardExtRewarders/Competition/List.tsx b/src/components/Scheme/ContributionRewardExtRewarders/Competition/List.tsx index 2f74b5ea6..4ae5e3f65 100644 --- a/src/components/Scheme/ContributionRewardExtRewarders/Competition/List.tsx +++ b/src/components/Scheme/ContributionRewardExtRewarders/Competition/List.tsx @@ -9,6 +9,7 @@ import { getArc } from "arc"; import { CompetitionStatusEnum, CompetitionStatus } from "./utils"; import Card from "./Card"; import * as css from "./Competitions.scss"; +import { standardPolling } from "lib/util"; interface IExternalProps { daoState: IDAOState; @@ -83,7 +84,7 @@ class CompetitionsList extends React.Component { public render(): RenderOutput { - const { daoState, scheme, proposals} = this.props; + const { daoState, scheme, proposals } = this.props; const daoAvatarAddress = daoState.address; return @@ -105,7 +106,7 @@ class CompetitionsList extends React.Component { export default withSubscription({ wrappedComponent: CompetitionsList, loadingComponent: null, - errorComponent: (props) =>
{ props.error.message }
, + errorComponent: (props) =>
{props.error.message}
, checkForUpdate: [], createObservable: async (props: IExternalProps) => { // prime the cache before creating the observable... @@ -137,7 +138,7 @@ export default withSubscription({ `; const arc = await getArc(); - await arc.sendQuery(cacheQuery, {subscribe: true}); + await arc.sendQuery(cacheQuery, standardPolling()); // end cache priming // TODO: next lines can use some cleanup up diff --git a/src/components/Scheme/ContributionRewardExtRewarders/Competition/utils.ts b/src/components/Scheme/ContributionRewardExtRewarders/Competition/utils.ts index 5d476f6ff..ad95f31d5 100644 --- a/src/components/Scheme/ContributionRewardExtRewarders/Competition/utils.ts +++ b/src/components/Scheme/ContributionRewardExtRewarders/Competition/utils.ts @@ -1,4 +1,9 @@ -import { ICompetitionProposalState, Competition, CompetitionSuggestion, ICompetitionSuggestionState, CompetitionVote, Address } from "@daostack/arc.js"; +import { ICompetitionProposalState, + Competition, + CompetitionSuggestion, + ICompetitionSuggestionState, + CompetitionVote, + Address } from "@daostack/arc.js"; import * as Redux from "redux"; import { ThunkAction } from "redux-thunk"; @@ -8,6 +13,7 @@ import { operationNotifierObserver } from "actions/arcActions"; import { IRootState } from "reducers"; import { Observable, of } from "rxjs"; import { map, mergeMap, toArray, first } from "rxjs/operators"; +import { GRAPH_POLL_INTERVAL } from "../../../../settings"; /** * Defined in the order that Competition cards should be sorted in the List component. @@ -56,8 +62,8 @@ export class CompetitionStatus { */ public get votingIsOver() { return ((this.status === CompetitionStatusEnum.Ended) || - (this.status === CompetitionStatusEnum.EndedNoWinners) || - (this.status === CompetitionStatusEnum.EndedNoSubmissions)); + (this.status === CompetitionStatusEnum.EndedNoWinners) || + (this.status === CompetitionStatusEnum.EndedNoSubmissions)); } /** * competition is over, with or without submissions or winners @@ -80,7 +86,7 @@ export const competitionStatus = (competition: ICompetitionProposalState): Compe const hasWinners = !!competition.numberOfWinningSuggestions; let status: CompetitionStatusEnum; - if (now.isBefore(startTime)){ + if (now.isBefore(startTime)) { status = CompetitionStatusEnum.NotOpenYet; } else if (now.isBefore(votingStartTime)) { if (now.isSameOrAfter(submissionsEndTime)) { @@ -105,7 +111,9 @@ export interface ICreateSubmissionOptions { tags: Array; } -export const createCompetitionSubmission = (proposalId: string, options: ICreateSubmissionOptions ): ThunkAction => { +const standardPolling = (poll: boolean, fetchAllData = false) => { return { polling: poll, pollInterval: GRAPH_POLL_INTERVAL, fetchAllData }; }; + +export const createCompetitionSubmission = (proposalId: string, options: ICreateSubmissionOptions): ThunkAction => { return async (dispatch: Redux.Dispatch, _getState: () => IRootState) => { try { const observer = operationNotifierObserver(dispatch, "Create Submission"); @@ -123,7 +131,7 @@ export interface IVoteSubmissionOptions { id: string; // actual id, not the counter } -export const voteForSubmission = (options: IVoteSubmissionOptions ): ThunkAction => { +export const voteForSubmission = (options: IVoteSubmissionOptions): ThunkAction => { return async (dispatch: Redux.Dispatch, _getState: () => IRootState) => { try { const observer = operationNotifierObserver(dispatch, "Vote Submission"); @@ -142,7 +150,7 @@ export interface IVoteSubmissionOptions { id: string; // actual id, not the counter } -export const redeemForSubmission = (options: IVoteSubmissionOptions ): ThunkAction => { +export const redeemForSubmission = (options: IVoteSubmissionOptions): ThunkAction => { return async (dispatch: Redux.Dispatch, _getState: () => IRootState) => { try { const observer = operationNotifierObserver(dispatch, "Redeem Submission"); @@ -160,7 +168,7 @@ export const redeemForSubmission = (options: IVoteSubmissionOptions ): ThunkActi export const getProposalSubmissions = (proposalId: string, subscribe = false): Observable> => { // fetchAllData so .state() comes from cache const competition = new Competition(proposalId, getArc()); - return competition.suggestions({}, { subscribe, fetchAllData: true }) + return competition.suggestions({}, standardPolling(subscribe, true)) .pipe( mergeMap(submissions => of(submissions).pipe( mergeMap(submissions => submissions), @@ -171,7 +179,7 @@ export const getProposalSubmissions = (proposalId: string, subscribe = false): O export const getSubmission = (id: string, subscribe = false): Observable => { const submission = new CompetitionSuggestion(id, getArc()); - return submission.state({ subscribe }); + return submission.state(standardPolling(subscribe)); }; export const getCompetitionVotes = (competitionId: string, voterAddress: Address, subscribe = false): Observable> => { @@ -179,14 +187,13 @@ export const getCompetitionVotes = (competitionId: string, voterAddress: Address /** * none of the current uses require the vote state */ - return competition.votes({ where: { voter: voterAddress } }, - { subscribe: subscribe, fetchAllData: true }); + return competition.votes({ where: { voter: voterAddress } }, standardPolling(subscribe, true)); }; const getSubmissionVotes = (submissionId: string, voterAddress?: Address, subscribe = false): Observable> => { // submissionId is the actual id, not the count const submission = new CompetitionSuggestion(submissionId, getArc()); - return submission.votes(voterAddress ? { where: { voter: voterAddress } } : {}, { subscribe, fetchAllData: true }); + return submission.votes(voterAddress ? { where: { voter: voterAddress } } : {}, standardPolling(subscribe, true)); }; export const getSubmissionVoterHasVoted = (submissionId: string, voterAddress: string, subscribe = false): Observable => { @@ -200,7 +207,7 @@ export const getSubmissionVoterHasVoted = (submissionId: string, voterAddress: s // export const primeCacheForSubmissionsAndVotes = (): Observable => { // return combineLatest( -// CompetitionSuggestion.search(getArc(), {}, { subscribe: true, fetchAllData: true }), -// CompetitionVote.search(getArc(), {}, { subscribe: true, fetchAllData: true }) +// CompetitionSuggestion.search(getArc(), {}, standardPolling(true)), +// CompetitionVote.search(getArc(), {}, standardPolling(true)) // ); // }; diff --git a/src/components/Scheme/ContributionRewardExtRewarders/DetailsPageRouter.tsx b/src/components/Scheme/ContributionRewardExtRewarders/DetailsPageRouter.tsx index 3ebdee25e..2f3638035 100644 --- a/src/components/Scheme/ContributionRewardExtRewarders/DetailsPageRouter.tsx +++ b/src/components/Scheme/ContributionRewardExtRewarders/DetailsPageRouter.tsx @@ -5,6 +5,7 @@ import { getArc } from "arc"; import { IDAOState, IProposalState, Address } from "@daostack/arc.js"; import Loading from "components/Shared/Loading"; import { getCrxRewarderComponent, CrxRewarderComponentType } from "components/Scheme/ContributionRewardExtRewarders/rewardersProps"; +import { standardPolling } from "lib/util"; interface IExternalProps extends RouteComponentProps { currentAccountAddress: Address; @@ -51,11 +52,11 @@ class DetailsPageRouter extends React.Component * that will completely hose the crxDetailsComponent */ return ; } @@ -63,11 +64,11 @@ class DetailsPageRouter extends React.Component export default withSubscription({ wrappedComponent: DetailsPageRouter, - loadingComponent: , + loadingComponent: , errorComponent: null, checkForUpdate: [], createObservable: (props: IProps) => { const arc = getArc(); - return arc.proposal(props.proposalId).state( { subscribe: true }); + return arc.proposal(props.proposalId).state(standardPolling()); }, }); diff --git a/src/components/Scheme/SchemeContainer.tsx b/src/components/Scheme/SchemeContainer.tsx index 5dd07490d..3e2acbc5c 100644 --- a/src/components/Scheme/SchemeContainer.tsx +++ b/src/components/Scheme/SchemeContainer.tsx @@ -22,6 +22,7 @@ import SchemeInfoPage from "./SchemeInfoPage"; import SchemeProposalsPage from "./SchemeProposalsPage"; import SchemeOpenBountyPage from "./SchemeOpenBountyPage"; import * as css from "./Scheme.scss"; +import { standardPolling } from "lib/util"; interface IDispatchProps { showNotification: typeof showNotification; @@ -77,9 +78,8 @@ class SchemeContainer extends React.Component { */ daoState={this.props.daoState} currentAccountAddress={this.props.currentAccountAddress} - scheme={this.props.data[0]}crxRewarderProps={crxRewarderProps} />; - private contributionsRewardExtTabHtml = () => (props: any) => - { + scheme={this.props.data[0]} crxRewarderProps={crxRewarderProps} />; + private contributionsRewardExtTabHtml = () => (props: any) => { if (!this.state.crxListComponent) { return null; } @@ -92,7 +92,7 @@ class SchemeContainer extends React.Component { const newState = {}; if (!this.state.crxRewarderProps) { - Object.assign(newState, { crxRewarderProps: await getCrxRewarderProps(this.props.data[0]) } ); + Object.assign(newState, { crxRewarderProps: await getCrxRewarderProps(this.props.data[0]) }); } if (!this.state.crxListComponent) { @@ -198,7 +198,7 @@ class SchemeContainer extends React.Component { }
- { isProposalScheme ? + {isProposalScheme ? inInfoTab ?
@@ -222,7 +222,7 @@ class SchemeContainer extends React.Component { href="#!" onClick={isActive ? this.handleNewProposal : null} > - + New Proposal + + New Proposal
: "" @@ -250,7 +250,7 @@ class SchemeContainer extends React.Component { const SubscribedSchemeContainer = withSubscription({ wrappedComponent: SchemeContainer, - loadingComponent: , + loadingComponent: , errorComponent: null, checkForUpdate: ["schemeId"], createObservable: async (props: IProps) => { @@ -261,9 +261,9 @@ const SubscribedSchemeContainer = withSubscription({ // why are we doing this for all schemes and not just the scheme we care about here? await props.daoState.dao.proposals( // eslint-disable-next-line @typescript-eslint/camelcase - {where: { stage_in: [IProposalStage.Boosted, IProposalStage.QuietEndingPeriod, IProposalStage.Queued, IProposalStage.PreBoosted, IProposalStage.Executed ]}}, + { where: { stage_in: [IProposalStage.Boosted, IProposalStage.QuietEndingPeriod, IProposalStage.Queued, IProposalStage.PreBoosted, IProposalStage.Executed] } }, // eslint-disable-next-line @typescript-eslint/no-empty-function - { fetchAllData: true, subscribe: true }).subscribe(() => {}); + standardPolling(true)).subscribe(() => { }); // end cache priming const schemeState = await scheme.state().pipe(first()).toPromise(); @@ -277,18 +277,19 @@ const SubscribedSchemeContainer = withSubscription({ let approvedProposals: Observable>; if (hasRewarderContract(schemeState)) { approvedProposals = props.daoState.dao.proposals( + { // eslint-disable-next-line @typescript-eslint/camelcase - { where: { scheme: scheme.id, stage_in: [IProposalStage.Executed]}, + where: { scheme: scheme.id, stage_in: [IProposalStage.Executed] }, orderBy: "closingAt", orderDirection: "desc", }, - { subscribe: true, fetchAllData: true }) + standardPolling(true)) .pipe( // work on each array individually so that toArray can perceive closure on the stream of items in the array mergeMap(proposals => of(proposals).pipe( mergeMap(proposals => proposals), mergeMap(proposal => proposal.state().pipe(first())), - filter((proposal: IProposalState) => proposal.winningOutcome === IProposalOutcome.Pass ), + filter((proposal: IProposalState) => proposal.winningOutcome === IProposalOutcome.Pass), toArray()) ) ); @@ -298,9 +299,9 @@ const SubscribedSchemeContainer = withSubscription({ return combineLatest( // refetch so we can subscribe. Don't worry, has been cached - arc.scheme(props.schemeId).state({ subscribe: true }), + arc.scheme(props.schemeId).state(standardPolling()), // Find the SchemeManager scheme if this dao has one - Scheme.search(arc, {where: { dao: props.daoState.id, name: "SchemeRegistrar" }}).pipe(mergeMap((scheme: Array): Observable => scheme[0] ? scheme[0].state() : of(null))), + Scheme.search(arc, { where: { dao: props.daoState.id, name: "SchemeRegistrar" } }).pipe(mergeMap((scheme: Array): Observable => scheme[0] ? scheme[0].state() : of(null))), approvedProposals ); }, diff --git a/src/components/Scheme/SchemeProposalsPage.tsx b/src/components/Scheme/SchemeProposalsPage.tsx index 7fbc642ce..6b2dcf58e 100644 --- a/src/components/Scheme/SchemeProposalsPage.tsx +++ b/src/components/Scheme/SchemeProposalsPage.tsx @@ -18,6 +18,7 @@ import { showNotification } from "reducers/notifications"; import TrainingTooltip from "components/Shared/TrainingTooltip"; import ProposalCard from "../Proposal/ProposalCard"; import * as css from "./SchemeProposals.scss"; +import { standardPolling } from "lib/util"; // For infinite scrolling const PAGE_SIZE_QUEUED = 100; @@ -146,7 +147,7 @@ const SubscribedProposalsPreBoosted = withSubscription { @@ -157,7 +158,7 @@ const SubscribedProposalsPreBoosted = withSubscription { @@ -243,7 +244,7 @@ const SubscribedProposalsQueued = withSubscription { public render(): RenderOutput { const { data } = this.props; - const [proposalsBoosted, allProposals ] = data; + const [proposalsBoosted, allProposals] = data; const { currentAccountAddress, daoState, scheme } = this.props; - let proposalCount=0; + let proposalCount = 0; const boostedProposalsHTML = ( { proposalsBoosted.map((proposal: Proposal): any => ( - 0}/> + 0} /> ))} @@ -286,14 +287,14 @@ class SchemeProposalsPage extends React.Component { {(allProposals.length === 0) ?
- +
No upcoming proposals

You can be the first one to create a {schemeFriendlyName} proposal today! :)

- Back to plugins + Back to plugins
@@ -307,7 +308,7 @@ class SchemeProposalsPage extends React.Component { {proposalsBoosted.length === 0 ?
- +
: " " } @@ -402,9 +403,9 @@ const SubscribedSchemeProposalsPage = withSubscription // eslint-disable-next-line @typescript-eslint/camelcase where: { scheme: schemeId, stage_in: [IProposalStage.Boosted, IProposalStage.QuietEndingPeriod] }, orderBy: "boostedAt", - }, { subscribe: true }), + }, standardPolling()), // big subscription query to make all other subscription queries obsolete - arc.getObservable(bigProposalQuery, { subscribe: true }) as Observable, + arc.getObservable(bigProposalQuery, standardPolling()) as Observable, ); }, }); diff --git a/src/layouts/Header.tsx b/src/layouts/Header.tsx index 2e8712151..009925747 100644 --- a/src/layouts/Header.tsx +++ b/src/layouts/Header.tsx @@ -25,6 +25,7 @@ import { ETHDENVER_OPTIMIZATION } from "../settings"; import * as css from "./App.scss"; import ProviderConfigButton from "layouts/ProviderConfigButton"; import Tooltip from "rc-tooltip"; +import { standardPolling } from "lib/util"; interface IExternalProps extends RouteComponentProps { } @@ -181,13 +182,13 @@ class Header extends React.Component {
{ @@ -213,7 +214,7 @@ class Header extends React.Component {
: "" }
- { currentAccountAddress ? + {currentAccountAddress ?
@@ -242,25 +243,25 @@ class Header extends React.Component {
- Full Profile + Full Profile
- { accountIsEnabled ? + {accountIsEnabled ?
Provider
{web3ProviderInfo.name}
- { providerHasConfigUi(web3Provider) ? + {providerHasConfigUi(web3Provider) ?
: "" } -
Log out
+
Log out
: -
Connect
} +
Connect
}
: @@ -269,7 +270,7 @@ class Header extends React.Component {
@@ -277,7 +278,7 @@ class Header extends React.Component {
@@ -299,7 +300,7 @@ const SubscribedHeader = withSubscription({ if (props.daoAvatarAddress) { const arc = getArc(); // subscribe if only to get DAO reputation supply updates - return arc.dao(props.daoAvatarAddress).state({ subscribe: true }); + return arc.dao(props.daoAvatarAddress).state(standardPolling()); } else { return of(null); } diff --git a/src/layouts/SidebarMenu.tsx b/src/layouts/SidebarMenu.tsx index 1a247448d..b433f40b0 100644 --- a/src/layouts/SidebarMenu.tsx +++ b/src/layouts/SidebarMenu.tsx @@ -9,7 +9,7 @@ import FollowButton from "components/Shared/FollowButton"; import withSubscription, { ISubscriptionProps } from "components/Shared/withSubscription"; import { generate } from "geopattern"; import Analytics from "lib/analytics"; -import { baseTokenName, ethErrorHandler, formatTokens, genName, getExchangesList, supportedTokens, fromWei, ethBalance, linkToEtherScan } from "lib/util"; +import { baseTokenName, ethErrorHandler, formatTokens, genName, getExchangesList, supportedTokens, fromWei, ethBalance, linkToEtherScan, standardPolling } from "lib/util"; import { parse } from "query-string"; import * as React from "react"; import { matchPath, Link, RouteComponentProps } from "react-router-dom"; @@ -79,7 +79,7 @@ class SidebarMenu extends React.Component { } private drawNavHeadingLine = () => { - return ; + return ; } public daoMenu() { @@ -107,12 +107,12 @@ class SidebarMenu extends React.Component {

Learn how to MemeDAO

: dao.name === "ETHBerlin dHack.io" ?

- For more info join our TG group - + For more info join our TG group - t.me/dhack0

: dao.name === "Identity" ?

- A curated registry of identities on the Ethereum blockchain.  + A curated registry of identities on the Ethereum blockchain.  How to register.

:

New to DAOstack? Visit the help center to get started.

@@ -188,9 +188,8 @@ class SidebarMenu extends React.Component {
  • - + {formatTokens(dao.reputationTotalSupply)} REP
  • @@ -217,7 +216,7 @@ class SidebarMenu extends React.Component { return (
    - { this.props.daoAvatarAddress && this.props.data ? this.daoMenu() : ""} + {this.props.daoAvatarAddress && this.props.data ? this.daoMenu() : ""}
      @@ -264,7 +263,7 @@ class SidebarMenu extends React.Component { } /***** DAO ETH Balance *****/ -interface IEthProps extends ISubscriptionProps { +interface IEthProps extends ISubscriptionProps { dao: IDAOState; } @@ -330,7 +329,7 @@ const SubscribedSidebarMenu = withSubscription({ createObservable: (props: IProps) => { if (props.daoAvatarAddress) { const arc = getArc(); - return arc.dao(props.daoAvatarAddress).state({ subscribe: true } ); + return arc.dao(props.daoAvatarAddress).state(standardPolling()); } else { return of(null); } diff --git a/src/lib/util.ts b/src/lib/util.ts index fb1711a34..37efed4e4 100644 --- a/src/lib/util.ts +++ b/src/lib/util.ts @@ -16,6 +16,7 @@ import "moment"; import * as moment from "moment-timezone"; import { getArc } from "../arc"; import { ISimpleMessagePopupProps } from "components/Shared/SimpleMessagePopup"; +import { GRAPH_POLL_INTERVAL } from "../settings"; const tokens = require("data/tokens.json"); const exchangesList = require("data/exchangesList.json"); @@ -702,3 +703,6 @@ export function safeMoment(dateSpecifier: moment.Moment | Date | number | string throw new Error(`safeMoment: unknown type: ${typeof dateSpecifier}`); } } + +export const standardPolling = (fetchAllData = false) => +{ return { polling: true, pollInterval: GRAPH_POLL_INTERVAL, fetchAllData }; }; diff --git a/src/settings.ts b/src/settings.ts index b6ed19a8d..ef0b86c14 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -2,6 +2,7 @@ export const ETHDENVER_OPTIMIZATION = true; // if this is true, we do get the contractInfos from a locally stored file in ./data instead of from the subgraph export const USE_CONTRACTINFOS_CACHE = false; +export const GRAPH_POLL_INTERVAL = 30000; import BurnerConnectProvider from "@burner-wallet/burner-connect-provider"; import WalletConnectProvider from "@walletconnect/web3-provider"; const Torus = require("@toruslabs/torus-embed"); From 2f292b39940a86669accfc6bfbbd644227cf8fcb Mon Sep 17 00:00:00 2001 From: Burak Benligiray Date: Sun, 4 Oct 2020 13:37:59 +0300 Subject: [PATCH 2/4] Add API3 DAO GenericScheme plugins for Rinkeby (#2147) * Add API3 token to Rinkeby * Add GenericScheme plugins for API3 DAO --- data/tokens.json | 5 + .../schemes/Api3Token.json | 86 ++++++++ .../schemes/TimelockManager.json | 184 ++++++++++++++++++ 3 files changed, 275 insertions(+) create mode 100644 src/genericSchemeRegistry/schemes/Api3Token.json create mode 100644 src/genericSchemeRegistry/schemes/TimelockManager.json diff --git a/data/tokens.json b/data/tokens.json index 23579f62a..d5604a38a 100644 --- a/data/tokens.json +++ b/data/tokens.json @@ -113,6 +113,11 @@ "decimals": 6, "name": "USD Coin", "symbol": "USDC" + }, + "0x3426d85D140c85C5ebB6E4D343C5be8e4E001869": { + "decimals": 18, + "name": "API3 token", + "symbol": "API3" } } }, diff --git a/src/genericSchemeRegistry/schemes/Api3Token.json b/src/genericSchemeRegistry/schemes/Api3Token.json new file mode 100644 index 000000000..ad08c069b --- /dev/null +++ b/src/genericSchemeRegistry/schemes/Api3Token.json @@ -0,0 +1,86 @@ +{ + "name": "Api3Token", + "addresses": { + "main": [ + "" + ], + "rinkeby": [ + "0xA82aEF6C92C421D70923E91300631A39932c5E44" + ], + "private": [ + "" + ] + }, + "actions": [ + { + "id": "approve", + "label": "Approve API3 tokens", + "description": "Approve address to transfer amount-many API3 tokens", + "notes": "https://github.com/api3dao/api3-contracts/blob/master/packages/api3-token/contracts/Api3Token.sol", + "fields": [ + { + "label": "Address that will be approved to transfer the tokens", + "name": "spender", + "placeholder": "Address (0x0000...)" + }, + { + "decimals": 18, + "label": "Number of API3 tokens to be approved", + "name": "amount", + "unit": "API3", + "placeholder": "Number of tokens (123)" + } + ], + "abi": { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + }, + { + "id": "transferOwnership", + "label": "Tranfer ownership of the API3Token contract", + "description": "Tranfer ownership of the API3Token contract to newOwner", + "notes": "https://github.com/api3dao/api3-contracts/blob/master/packages/api3-token/contracts/Api3Token.sol", + "fields": [ + { + "label": "Address that will receive the ownership of the API3Token contract", + "name": "newOwner", + "placeholder": "Address (0x0000...)" + } + ], + "abi": { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + } + ] +} diff --git a/src/genericSchemeRegistry/schemes/TimelockManager.json b/src/genericSchemeRegistry/schemes/TimelockManager.json new file mode 100644 index 000000000..e5eb946e7 --- /dev/null +++ b/src/genericSchemeRegistry/schemes/TimelockManager.json @@ -0,0 +1,184 @@ +{ + "name": "TimelockManager", + "addresses": { + "main": [ + "" + ], + "rinkeby": [ + "0xBEAFB0FB210D6A60550991632db7B88a2B2dece8" + ], + "private": [ + "" + ] + }, + "actions": [ + { + "id": "transferOwnership", + "label": "Tranfer ownership of the TimelockManager contract", + "description": "Tranfer ownership of the TimelockManager contract to newOwner", + "notes": "https://github.com/api3dao/api3-contracts/blob/master/packages/api3-dao-v1/contracts/TimelockManager.sol", + "fields": [ + { + "label": "Address that will receive the ownership of the TimelockManager contract", + "name": "newOwner", + "placeholder": "Address (0x0000...)" + } + ], + "abi": { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + }, + { + "id": "updateApi3Pool", + "label": "Updates the address of the API3Pool contract", + "description": "Updates the address of the API3Pool contract to api3PoolAddress", + "notes": "https://github.com/api3dao/api3-contracts/blob/master/packages/api3-dao-v1/contracts/TimelockManager.sol", + "fields": [ + { + "label": "Updated API3Pool contract address", + "name": "api3PoolAddress", + "placeholder": "Address (0x0000...)" + } + ], + "abi": { + "inputs": [ + { + "internalType": "address", + "name": "api3PoolAddress", + "type": "address" + } + ], + "name": "updateApi3Pool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + }, + { + "id": "transferAndLock", + "label": "Transfers and locks API3 tokens", + "description": "Transfers and locks amount-many API3 tokens from source for owner to be released at releaseTime", + "notes": "https://github.com/api3dao/api3-contracts/blob/master/packages/api3-dao-v1/contracts/TimelockManager.sol", + "fields": [ + { + "label": "Source of the API3 tokens (most likely the API3 DAO)", + "name": "source", + "placeholder": "Address (0x0000...)" + }, + { + "label": "The owner for whom the tokens are being locked for", + "name": "owner", + "placeholder": "Address (0x0000...)" + }, + { + "decimals": 18, + "label": "Number of API3 tokens to be locked", + "name": "amount", + "unit": "API3", + "placeholder": "Number of tokens (123)" + }, + { + "label": "UTC timestamp for when the tokens will be released", + "name": "releaseTime", + "placeholder": "Timestamp (123...)" + } + ], + "abi": { + "inputs": [ + { + "internalType": "address", + "name": "source", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "releaseTime", + "type": "uint256" + } + ], + "name": "transferAndLock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + }, + { + "id": "transferAndLockMultiple", + "label": "Transfers and locks API3 tokens in batch", + "description": "Transfers and locks amount-many API3 tokens from source for owner to be released at releaseTime in batch", + "notes": "https://github.com/api3dao/api3-contracts/blob/master/packages/api3-dao-v1/contracts/TimelockManager.sol", + "fields": [ + { + "label": "Source of the API3 tokens (most likely the API3 DAO)", + "name": "source", + "placeholder": "Address (0x0000...)" + }, + { + "label": "The owners for whom the tokens are being locked for", + "name": "owners", + "placeholder": "Addresses ([0x0000..., 0x0000..., ...])" + }, + { + "decimals": 18, + "label": "Numbers of API3 tokens to be locked", + "name": "amounts", + "unit": "API3", + "placeholder": "Numbers of tokens ([123, 456, ...])" + }, + { + "label": "UTC timestamps for when the tokens will be released", + "name": "releaseTimes", + "placeholder": "Timestamps ([123, 456, ...])" + } + ], + "abi": { + "inputs": [ + { + "internalType": "address", + "name": "source", + "type": "address" + }, + { + "internalType": "address[]", + "name": "owners", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "releaseTimes", + "type": "uint256[]" + } + ], + "name": "transferAndLockMultiple", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + } + ] +} From 9e28c3167326d6b4447883f4d23662eb07a145fc Mon Sep 17 00:00:00 2001 From: Doug Kent Date: Sun, 4 Oct 2020 06:52:07 -0400 Subject: [PATCH 3/4] upgrade node and npm (#2153) --- .travis.yml | 2 +- package.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 402bfe2cc..e8016a658 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: node_js -node_js: 12.16.2 +node_js: 12.18.4 addons: apt: update: true diff --git a/package.json b/package.json index 5881138dd..2e266443e 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,8 @@ "url": "git+https://github.com/daostack/alchemy.git" }, "engines": { - "node": "12.16.2", - "npm": "6.14.4" + "node": "12.18.4", + "npm": "6.14.6" }, "jest": { "testURL": "http://127.0.0.1:3000/", From a4849e63510c8543eb2e4a9cca486cfe1ecfa7e1 Mon Sep 17 00:00:00 2001 From: Doug Kent Date: Tue, 6 Oct 2020 07:16:05 -0400 Subject: [PATCH 4/4] changle log and bump version (#2164) --- CHANGELOG.md | 4 ++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01bbd71a5..cca16f762 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.10.17 + - Bugs Fixed + - Fixed issues with automated update of blockchain data by switching from a websocket to a polling interface with the subgraph + ## 0.10.16 - Features Added - show account holdings even when out of scope of a DAO diff --git a/package-lock.json b/package-lock.json index 06e3ed813..ae9b5f993 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "alchemy-client", - "version": "0.10.16", + "version": "0.10.17", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 2e266443e..2eada9200 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "alchemy-client", - "version": "0.10.16", + "version": "0.10.17", "description": "An app for collaborative networks (DAOs), based on the DAO stack.", "author": "DAOstack", "license": "GPL-3.0",