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

Add contract Graph API mock #73

Merged
merged 12 commits into from
Apr 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions .github/workflows/check-api-compatibility.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Check dApp API compatibility

on:
push:
branches:
- main
paths:
- "packages/web/schema.graphql"

pull_request:
branches:
- main
types:
- opened
- synchronize
paths:
- "packages/web/schema.graphql"

jobs:
check:
name: Check GraphQL schema compatibility
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
with:
submodules: recursive

- name: Setup NodeJS
uses: actions/setup-node@v2
with:
node-version: "16"
cache: "yarn"

- name: Install dependencies
run: yarn --ignore-scripts

- name: Generate types
run: |-
cd packages/web
yarn gen:gql-types

- name: Build dApp
run: |-
cd packages/web
yarn build

45 changes: 45 additions & 0 deletions .github/workflows/verify-dapp.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Verify dApp

on:
push:
branches:
- main
paths:
- "packages/web/**"

pull_request:
branches:
- main
types:
- opened
- synchronize
paths:
- "packages/web/**"

jobs:
# Add linting job after migration to nextjs version with given fix https://github.com/vercel/next.js/issues/44424

test:
name: Test dApp
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
with:
submodules: recursive

- name: Setup NodeJS
uses: actions/setup-node@v2
with:
node-version: "16"
cache: "yarn"

- name: Install dependencies
run: yarn --ignore-scripts

- name: Run tests
run: |-
cd packages/web
yarn test:ci


Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
name: Verify Contracts PR
name: Verify Smart Contracts

on:
push:
branches:
- main
paths:
- "packages/contracts/**"

pull_request:
branches:
- main
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Yield Aggregator dApp and protocol for safe and high reward liquidity mining

This mono-repository contains protocol contracts and dApp code, as well as all related packages.

For a list of known development issues related to Lerna monorepo, see [development.md](https://github.com/eonian-core/farm/tree/main/development.md).

### Structure

* `packages/contracts` - Protocol contracts.
Expand Down Expand Up @@ -43,6 +45,9 @@ yarn
* `yarn test:contracts` - Test only contracts
* `dev:contracts` - Set up a development environment for contracts. Watch file changes and rerun tests.




## Deployment

The deployment process focused on implementing GitOps practices. Basically, it means all master (main) builds go to production directly. For a web application, PRs also deploy to a preview environment.
Expand Down
32 changes: 32 additions & 0 deletions development.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Known Development Issues

## Installation of dependencies

Fail during installation of dependency in one of the packages.
Example `error An unexpected error occurred: "expected workspace package to exist for \"yargs\"".`

Issue still not fixed by yarn: https://github.com/yarnpkg/yarn/issues/7734.

### Solution

Go to the root directory and run `yarn workspace [package-name] add ...` to add the package. Use `@eonian/web` as the package name for the web package and `@eonian/contracts` for the contracts package.

## Graphql types code generation

Fail during code generation of graphql types.
Example:

```bash
Cannot use GraphQLScalarType "BigDecimal" from another module or realm.
Ensure that there is only one instance of "graphql" in the node_modules
```

Remove `nohoist` from the root `package.json`, delete node_modules in root and all packages, and run `yarn` again. Be aware, removing `nohoist` can cause failures in contracts package.

## Jest is not working properly with ESM modules

Jest is not working properly with ESM modules. It fails to run tests by using the normal `jest` command in the web package.

### Solution

Add a command which enables ESM modules for node and then run jest. For web package it is `yarn jest`
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "root",
"name": "eonian",
"private": true,
"scripts": {
"bootstrap": "lerna bootstrap --use-workspaces",
Expand All @@ -20,10 +20,6 @@
"packages/*"
],
"nohoist": [
"**/ts-node",
"**/ts-node/**",
"**/typescript",
"**/typescript/**",
"**/typechain",
"**/typechain/**",
"**/@typechain",
Expand All @@ -44,5 +40,9 @@
"generate-lockfile": "^0.0.12",
"lerna": "^5.1.6",
"nx": "^14.3.6"
},
"dependencies": {
"glob": "^8.0.1",
"yargs": "^17.6.2"
}
}
5 changes: 5 additions & 0 deletions packages/web/.env
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
# Feature Flags

NEXT_PUBLIC_FEATURE_FAQ_PAGE=true
NEXT_PUBLIC_FEATURE_COMMUNITY_PAGE=true
NEXT_PUBLIC_FEATURE_MISSION_PAGE=true
NEXT_PUBLIC_FEATURE_SECURITY_PAGE=true

# API
NEXT_PUBLIC_GRAPH_URL=http://localhost:4000
26 changes: 23 additions & 3 deletions packages/web/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,38 @@ yarn dev

It will start

* NextJS application at [http://localhost:3000](http://localhost:3000) and open page automatically
* NextJS application at [http://localhost:3000](http://localhost:3000) and the open page automatically
* Storybook at [http://localhost:6006](http://localhost:6006) or another port of it is busy

### Storybook

For development of components and independent screens there used Stroybook.
To start it locally use the following command:
For the development of components and independent screens, there used Storybook.
To start it locally, use the following command:

```bash
yarn storybook
```

### GraphQl API

For querying data from the blockchain and other services, there used GraphQL API.

#### Mocking Server

The mocking server allows mocking this API for development purposes. To start it locally, use the following command:

```bash
yarn mock
```

#### Generate Introspection Types

To generate types for the GraphQL API, use the following command:

```bash
yarn gen:gql-types
```

### CDN

* <https://vercel.com/eonian/farm-app> - Web app project in Vercel
Expand Down
12 changes: 12 additions & 0 deletions packages/web/app/api/apollo.client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { ApolloClient, InMemoryCache, MutationOptions, OperationVariables, QueryOptions } from '@apollo/client';

export const client = new ApolloClient({
uri: process.env.GRAPH_URL || 'http://localhost:4000/',
cache: new InMemoryCache(),
});

export const query = async <T = any, TVariables extends OperationVariables = OperationVariables>(options: QueryOptions<TVariables, T>) =>
client.query<T, TVariables>(options);

export const mutate = async <TData = any, TVariables extends OperationVariables = OperationVariables, TContext extends Record<string, any> = Record<string, any>, TCache extends InMemoryCache = InMemoryCache>(options: MutationOptions<TData, TVariables, TContext>) =>
client.mutate<TData, TVariables, TContext, TCache>(options);
31 changes: 31 additions & 0 deletions packages/web/app/api/get-vaults.query.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { gql } from '@apollo/client';
import { query } from './apollo.client';
import {GetVaultsQuery} from './gql/graphql';

export const GetVaults = gql`
query GetVaults {
vaults {
underlyingAsset {
address
name
symbol
decimals
}
totalBalance
interestRate
lastHarvestTime
address
name
symbol
decimals
}
}
`;

export type {GetVaultsQuery}

/**
* Get list of Vaults
* @example getVaults().then(console.log)
* */
export const getVaults = () => query<GetVaultsQuery>({ query: GetVaults })
48 changes: 48 additions & 0 deletions packages/web/app/api/gql/fragment-masking.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { ResultOf, DocumentTypeDecoration, } from '@graphql-typed-document-node/core';


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 useFragment<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: FragmentType<DocumentTypeDecoration<TType, any>>
): TType;
// return nullable if `fragmentType` is nullable
export function useFragment<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 useFragment<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 useFragment<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>> | null | undefined
): ReadonlyArray<TType> | null | undefined;
export function useFragment<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>;
}
42 changes: 42 additions & 0 deletions packages/web/app/api/gql/gql.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/* 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 = {
"\n query GetVaults {\n vaults {\n underlyingAsset {\n address\n name\n symbol\n decimals\n }\n totalBalance\n interestRate\n lastHarvestTime\n address\n name\n symbol\n decimals\n }\n }\n": types.GetVaultsDocument,
};

/**
* 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: "\n query GetVaults {\n vaults {\n underlyingAsset {\n address\n name\n symbol\n decimals\n }\n totalBalance\n interestRate\n lastHarvestTime\n address\n name\n symbol\n decimals\n }\n }\n"): (typeof documents)["\n query GetVaults {\n vaults {\n underlyingAsset {\n address\n name\n symbol\n decimals\n }\n totalBalance\n interestRate\n lastHarvestTime\n address\n name\n symbol\n decimals\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