Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat: historical proposals #112

Merged
merged 33 commits into from
Aug 3, 2023
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
3e92a3b
feat: add proposalsByGroupPolicyAddress query
wgwz Jul 19, 2023
ed693e8
fix: modify ProposalFragment
wgwz Jul 19, 2023
768f57f
WIP: graphql-request and react-query
wgwz Jul 20, 2023
4f1f4d8
feat: use react-query and graphql-request
wgwz Jul 20, 2023
8d107d4
feat: add useGraphQLClient and useGroupHistoricalProposals
wgwz Jul 21, 2023
17fa36a
fix: use provider for graphql client
wgwz Jul 24, 2023
455fc54
chore: add overwrite flag in codegen config
wgwz Jul 24, 2023
21ce8cf
chore: tiny formatting change for graphql query
wgwz Jul 24, 2023
71a2a9b
fix: parse historical proposals into UIProposal[]
wgwz Jul 24, 2023
c23c16f
feat: add historical proposals on groups-proposals-table
wgwz Jul 24, 2023
7d0d157
fix: rename fragment masking helper function
wgwz Jul 25, 2023
fa0bfe3
fix: add eslintignore to lint command and ignore src/gql/
wgwz Jul 25, 2023
023218d
fix: apply linter on some files
wgwz Jul 25, 2023
38aaab9
chore: fix lint problems in hooks/use-query
wgwz Jul 25, 2023
f68b38b
chore: remove sort
wgwz Jul 25, 2023
b272ffa
fix: do not show execute button for historical proposals
wgwz Jul 25, 2023
afac8e7
fix: use better implementation with simpler type for useGroupHistoric…
wgwz Jul 25, 2023
6cc02f1
feat: render historical proposal on proposal page
wgwz Jul 25, 2023
2f893fd
fix: react key warning
wgwz Jul 25, 2023
77b8189
feat: add proposal final tally table
wgwz Jul 25, 2023
1aec1f3
chore: configure netlify with indexer api urls
wgwz Jul 25, 2023
0a6c9cc
fix: typo in final tally results table title
wgwz Jul 26, 2023
6e68dcd
fix: remove console.log statement
wgwz Jul 26, 2023
013f2b5
refactor: is inline conditionals for rendering the proposal page
wgwz Jul 26, 2023
81dee8c
fix: make onVote optional in ProposalSummary
wgwz Jul 26, 2023
ba6ab28
chore: remove unused AllProposals query
wgwz Jul 26, 2023
3fff005
refactor: follow hyphenated naming convention
wgwz Jul 26, 2023
591b7cf
refactor: dedupe conversion of historical proposal into UIProposals
wgwz Jul 26, 2023
1e8beeb
fix: use an index for proposal messages list
wgwz Jul 27, 2023
485220e
refactor: add helper function for converting executor result to code
wgwz Jul 27, 2023
c82b561
fix: show final tally result table if voting period is closed
wgwz Jul 31, 2023
f00bec5
chore: rename historicalProposal to historical-proposal
wgwz Jul 31, 2023
0da1360
Merge branch 'dev' into kyle/63-graphql-request-react-query
ryanchristo Aug 3, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.local.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
VITE_LOCAL_HOSTNAME=http://127.0.0.1
VITE_PROXY_URL_REGEN_MAINNET=http://api.registry.regen.network
VITE_PROXY_URL_REGEN_TESTNET=http://api-staging.registry.regen.network
VITE_INDEXER_GRAPHQL_API=http://localhost:5000/indexer/graphql
3 changes: 2 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ node_modules
dist
dist-ssr
*.local
node_modules/*
node_modules/*
src/gql/*
3 changes: 2 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ node_modules
dist
dist-ssr
*.local
node_modules/*
node_modules/*
src/gql/
15 changes: 15 additions & 0 deletions indexer-codegen.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { CodegenConfig } from '@graphql-codegen/cli'

const config: CodegenConfig = {
overwrite: true,
schema: 'http://localhost:5000/indexer/graphql',
documents: ['src/graphql/indexer/**/*.graphql'],
generates: {
'./src/gql/': {
preset: 'client',
presetConfig: { fragmentMasking: { unmaskFunctionName: 'getFragmentData' } },
},
},
}

export default config
6 changes: 6 additions & 0 deletions netlify.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
[context.production.environment]
VITE_INDEXER_GRAPHQL_API="https://api.registry.regen.network/indexer/graphql"

[context.deploy-preview.environment]
VITE_INDEXER_GRAPHQL_API="https://api-staging.registry.regen.network/indexer/graphql"

[[redirects]]
from = "/*"
to = "/index.html"
Expand Down
9 changes: 7 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"build": "tsc && vite build",
"serve": "vite preview",
"gen:theme-typings": "chakra-cli tokens ./src/theme",
"lint:fix": "eslint ./src --ext .jsx,.js,.ts,.tsx --fix --ignore-path ./.gitignore",
"lint:fix": "eslint ./src --ext .jsx,.js,.ts,.tsx --fix --ignore-path ./.gitignore --ignore-path ./.eslintignore",
"lint:format": "prettier --loglevel warn --write \"./**/*.{js,jsx,ts,tsx,css,md,json}\" ",
"lint": "yarn lint:format && yarn lint:fix ",
"test": "yarn vitest",
Expand Down Expand Up @@ -38,6 +38,8 @@
"chart.js": "^4.3.0",
"dayjs": "^1.11.8",
"framer-motion": "^10.12.8",
"graphql": "^16.7.1",
"graphql-request": "^5.0.0",
wgwz marked this conversation as resolved.
Show resolved Hide resolved
"ipfs-http-client": "^60.0.0",
"jotai": "^2.1.1",
"react": "^18.2.0",
Expand All @@ -55,6 +57,8 @@
"@babel/core": "^7.21.8",
"@chakra-ui/cli": "^2.4.1",
"@chakra-ui/storybook-addon": "^4.0.17",
"@graphql-codegen/cli": "^4.0.1",
"@graphql-codegen/client-preset": "^4.0.1",
"@keplr-wallet/types": "^0.11.59",
"@storybook/addon-actions": "^7.0.18",
"@storybook/addon-essentials": "^7.0.18",
Expand Down Expand Up @@ -87,8 +91,9 @@
"rollup-plugin-visualizer": "^5.9.0",
"storybook": "^7.0.18",
"storybook-addon-react-router-v6": "^1.0.2",
"ts-node": "^10.9.1",
"ts-proto": "^1.148.2",
"typescript": "^5.1.3",
"typescript": "^5.1.6",
"vite": "4.2.3",
"vite-plugin-checker": "^0.6.0",
"vite-plugin-fonts": "^0.7.0",
Expand Down
3 changes: 3 additions & 0 deletions src/components/organisms/group-proposals-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ export const GroupProposalsTable = ({
const baseProps = { key, proposal }
switch (proposal.status) {
case ProposalStatus.PROPOSAL_STATUS_ACCEPTED:
if (proposal.historical) {
return <Row {...baseProps} />
}
return <ExecuteRow {...baseProps} onExecute={onExecute} />
default:
return <Row {...baseProps} />
Expand Down
34 changes: 34 additions & 0 deletions src/components/organisms/proposal-final-tally-table.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { TallyResult } from '@regen-network/api/types/codegen/cosmos/group/v1/types'

import { Table, TableContainer, Tbody, Td, Th, Thead, Tr } from '@/atoms'
import { TableTitlebar } from '@/molecules/table-titlebar'

export const ProposalFinalTallyTable = ({
finalTallyResult,
}: {
finalTallyResult: TallyResult
}) => {
return (
<TableContainer>
<TableTitlebar title="Final Tally Results" />
<Table variant="striped" size="lg">
<Thead>
<Tr>
<Th>Yes</Th>
<Th>No</Th>
<Th>Abstain</Th>
<Th>No with veto</Th>
</Tr>
</Thead>
<Tbody>
<Tr>
<Td>{finalTallyResult.yesCount}</Td>
<Td>{finalTallyResult.noCount}</Td>
<Td>{finalTallyResult.abstainCount}</Td>
<Td>{finalTallyResult.noWithVetoCount}</Td>
</Tr>
</Tbody>
</Table>
</TableContainer>
)
}
9 changes: 7 additions & 2 deletions src/components/organisms/proposal-summary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const ProposalSummary = ({
votes,
}: {
group: UIGroup
onVote: (option: VoteOptionType) => void
onVote?: (option: VoteOptionType) => void
proposal: UIProposal
userVote?: Vote
votes?: Vote[]
Expand Down Expand Up @@ -114,6 +114,7 @@ function renderMessage(msg: any, groupPolicyAddress: string) {
case '/cosmos.bank.v1beta1.MsgSend':
return (
<SendReview
key={groupPolicyAddress}
wgwz marked this conversation as resolved.
Show resolved Hide resolved
groupPolicyAddress={groupPolicyAddress}
values={
{
Expand All @@ -129,6 +130,7 @@ function renderMessage(msg: any, groupPolicyAddress: string) {
case '/cosmos.staking.v1beta1.MsgDelegate':
return (
<StakeReview
key={groupPolicyAddress}
groupPolicyAddress={groupPolicyAddress}
values={
{
Expand All @@ -143,6 +145,7 @@ function renderMessage(msg: any, groupPolicyAddress: string) {
case '/cosmos.staking.v1beta1.MsgBeginRedelegate':
return (
<StakeReview
key={groupPolicyAddress}
groupPolicyAddress={groupPolicyAddress}
values={
{
Expand All @@ -157,6 +160,7 @@ function renderMessage(msg: any, groupPolicyAddress: string) {
case '/cosmos.staking.v1beta1.MsgUndelegate':
return (
<StakeReview
key={groupPolicyAddress}
groupPolicyAddress={groupPolicyAddress}
values={
{
Expand All @@ -171,6 +175,7 @@ function renderMessage(msg: any, groupPolicyAddress: string) {
case '/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward':
return (
<StakeReview
key={groupPolicyAddress}
groupPolicyAddress={groupPolicyAddress}
values={
{
Expand All @@ -182,6 +187,6 @@ function renderMessage(msg: any, groupPolicyAddress: string) {
/>
)
default:
return <JSONDisplay data={msg} />
return <JSONDisplay key={groupPolicyAddress} data={msg} />
}
}
66 changes: 66 additions & 0 deletions src/gql/fragment-masking.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { ResultOf, DocumentTypeDecoration, TypedDocumentNode } from '@graphql-typed-document-node/core';
import { FragmentDefinitionNode } from 'graphql';
import { Incremental } from './graphql';


export type FragmentType<TDocumentType extends DocumentTypeDecoration<any, any>> = TDocumentType extends DocumentTypeDecoration<
infer TType,
any
>
? [TType] extends [{ ' $fragmentName'?: infer TKey }]
? TKey extends string
? { ' $fragmentRefs'?: { [key in TKey]: TType } }
: never
: never
: never;

// return non-nullable if `fragmentType` is non-nullable
export function getFragmentData<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: FragmentType<DocumentTypeDecoration<TType, any>>
): TType;
// return nullable if `fragmentType` is nullable
export function getFragmentData<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: FragmentType<DocumentTypeDecoration<TType, any>> | null | undefined
): TType | null | undefined;
// return array of non-nullable if `fragmentType` is array of non-nullable
export function getFragmentData<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>>
): ReadonlyArray<TType>;
// return array of nullable if `fragmentType` is array of nullable
export function getFragmentData<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>> | null | undefined
): ReadonlyArray<TType> | null | undefined;
export function getFragmentData<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: FragmentType<DocumentTypeDecoration<TType, any>> | ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>> | null | undefined
): TType | ReadonlyArray<TType> | null | undefined {
return fragmentType as any;
}


export function makeFragmentData<
F extends DocumentTypeDecoration<any, any>,
FT extends ResultOf<F>
>(data: FT, _fragment: F): FragmentType<F> {
return data as FragmentType<F>;
}
export function isFragmentReady<TQuery, TFrag>(
queryNode: DocumentTypeDecoration<TQuery, any>,
fragmentNode: TypedDocumentNode<TFrag>,
data: FragmentType<TypedDocumentNode<Incremental<TFrag>, any>> | null | undefined
): data is FragmentType<typeof fragmentNode> {
const deferredFields = (queryNode as { __meta__?: { deferredFields: Record<string, (keyof TFrag)[]> } }).__meta__
?.deferredFields;

if (!deferredFields) return true;

const fragDef = fragmentNode.definitions[0] as FragmentDefinitionNode | undefined;
const fragName = fragDef?.name?.value;

const fields = (fragName && deferredFields[fragName]) || [];
return fields.length > 0 && fields.every(field => data && field in data);
}
52 changes: 52 additions & 0 deletions src/gql/gql.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/* eslint-disable */
import * as types from './graphql';
import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';

/**
* Map of all GraphQL operations in the project.
*
* This map has several performance disadvantages:
* 1. It is not tree-shakeable, so it will include all operations in the project.
* 2. It is not minifiable, so the string of a GraphQL query will be multiple times inside the bundle.
* 3. It does not support dead code elimination, so it will add unused operations.
*
* Therefore it is highly recommended to use the babel or swc plugin for production.
*/
const documents = {
"fragment ProposalItem on Proposal {\n type\n blockHeight\n txIdx\n msgIdx\n chainNum\n timestamp\n txHash\n id: proposalId\n status\n groupPolicyAddress\n groupPolicyVersion\n metadata\n proposers\n submitTime\n groupVersion\n groupPolicyAddress\n finalTallyResult\n votingPeriodEnd\n executorResult\n messages\n}": types.ProposalItemFragmentDoc,
"query ProposalsByGroupPolicyAddress($groupPolicyAddress: String!) {\n allProposals(condition: {groupPolicyAddress: $groupPolicyAddress}) {\n nodes {\n ...ProposalItem\n }\n }\n}": types.ProposalsByGroupPolicyAddressDocument,
"query ProposalsByProposalId($proposalId: BigInt!) {\n allProposals(condition: {proposalId: $proposalId}) {\n nodes {\n ...ProposalItem\n }\n }\n}": types.ProposalsByProposalIdDocument,
};

/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*
*
* @example
* ```ts
* const query = graphql(`query GetUser($id: ID!) { user(id: $id) { name } }`);
* ```
*
* The query argument is unknown!
* Please regenerate the types.
*/
export function graphql(source: string): unknown;

/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "fragment ProposalItem on Proposal {\n type\n blockHeight\n txIdx\n msgIdx\n chainNum\n timestamp\n txHash\n id: proposalId\n status\n groupPolicyAddress\n groupPolicyVersion\n metadata\n proposers\n submitTime\n groupVersion\n groupPolicyAddress\n finalTallyResult\n votingPeriodEnd\n executorResult\n messages\n}"): (typeof documents)["fragment ProposalItem on Proposal {\n type\n blockHeight\n txIdx\n msgIdx\n chainNum\n timestamp\n txHash\n id: proposalId\n status\n groupPolicyAddress\n groupPolicyVersion\n metadata\n proposers\n submitTime\n groupVersion\n groupPolicyAddress\n finalTallyResult\n votingPeriodEnd\n executorResult\n messages\n}"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "query ProposalsByGroupPolicyAddress($groupPolicyAddress: String!) {\n allProposals(condition: {groupPolicyAddress: $groupPolicyAddress}) {\n nodes {\n ...ProposalItem\n }\n }\n}"): (typeof documents)["query ProposalsByGroupPolicyAddress($groupPolicyAddress: String!) {\n allProposals(condition: {groupPolicyAddress: $groupPolicyAddress}) {\n nodes {\n ...ProposalItem\n }\n }\n}"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "query ProposalsByProposalId($proposalId: BigInt!) {\n allProposals(condition: {proposalId: $proposalId}) {\n nodes {\n ...ProposalItem\n }\n }\n}"): (typeof documents)["query ProposalsByProposalId($proposalId: BigInt!) {\n allProposals(condition: {proposalId: $proposalId}) {\n nodes {\n ...ProposalItem\n }\n }\n}"];

export function graphql(source: string) {
return (documents as any)[source] ?? {};
}

export type DocumentType<TDocumentNode extends DocumentNode<any, any>> = TDocumentNode extends DocumentNode< infer TType, any> ? TType : never;
Loading