Skip to content

Commit

Permalink
Improve methods supporting return type of any subgraph env
Browse files Browse the repository at this point in the history
  • Loading branch information
Fernando Ramirez committed Sep 28, 2023
1 parent 8e5e7b9 commit 42598df
Show file tree
Hide file tree
Showing 6 changed files with 241 additions and 81 deletions.
62 changes: 36 additions & 26 deletions src/business-logic/sdk/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,30 @@ import nullthrows from 'nullthrows'
import { getDevSubgraph } from '@subgraph/dev/subgraph'
import { getStagingSubgraph } from '@subgraph/staging/subgraph'
import { getProdSubgraph } from '@subgraph/prod/subgraph'
import { Sdk } from '@subgraph/common'
import { contracts } from '../../contracts/contracts'
import { TheBadge__factory, TheBadge } from '../../contracts/generated/typechain'
import fs from 'fs'
import { Sdk } from '@subgraph/common'

export type TheBadgeSDKConfigOptions = {
rpcProviderConfig: RPCProviderConfig
web3Provider?: Web3Provider
devMode?: boolean
}

export enum TheBadgeSDKEnv {
DEVELOPMENT = 'DEVELOPMENT',
STAGING = 'STAGING',
PRODUCTION = 'PRODUCTION',
}

export abstract class TheBadgeSDKConfig {
protected readonly chainId: SupportedChainsValues
protected readonly rpcProviderName: RPCProvider
protected readonly readOnlyProvider: JsonRpcProvider
protected readonly web3Provider: Web3Provider | undefined
protected readonly subgraph: ReturnType<Sdk>
protected readonly devMode: boolean
protected readonly env: TheBadgeSDKEnv

protected constructor(chainId: SupportedChainsValues, config: TheBadgeSDKConfigOptions) {
nullthrows(TheBadgeSDKConfig.isChainSupported(chainId) ? chainId : null, `Chain ID ${chainId} is not supported`)
Expand All @@ -39,8 +45,8 @@ export abstract class TheBadgeSDKConfig {
this.rpcProviderName = config.rpcProviderConfig.name
this.readOnlyProvider = defaultReadOnlyProvider
this.web3Provider = config.web3Provider
this.devMode = !!config.devMode
this.subgraph = this.getSubgraph(networkConfig)
this.env = this.resolveEnv(!!config.devMode, networkConfig)
this.subgraph = this.getSubgraph()
}

protected static getSupportedChainIds(): Array<number> {
Expand All @@ -61,35 +67,39 @@ export abstract class TheBadgeSDKConfig {
)
}

private getSubgraph(networkConfig: ChainConfig): ReturnType<Sdk> {
private getSubgraph(): ReturnType<Sdk> {
const fakeGeneratedSubgraphContent = fs.readFileSync('./src/subgraph/fakeGeneratedSubgraph.ts')
let envGeneratedSubgraphContent

if (networkConfig.isTestnet) {
if (this.devMode) {
// dev subgraph
const devGeneratedSubgraphContent = fs.readFileSync('./src/subgraph/dev/generated/subgraph.ts')
if (!devGeneratedSubgraphContent.equals(fakeGeneratedSubgraphContent)) {
return getDevSubgraph(this.chainId)
} else {
switch (this.env) {
case TheBadgeSDKEnv.DEVELOPMENT: // dev subgraph
envGeneratedSubgraphContent = fs.readFileSync('./src/subgraph/dev/generated/subgraph.ts')
if (envGeneratedSubgraphContent.equals(fakeGeneratedSubgraphContent)) {
throw new Error('No dev subgraph')
}
} else {
// staging subgraph
const stagingGeneratedSubgraphContent = fs.readFileSync('./src/subgraph/staging/generated/subgraph.ts')
if (!stagingGeneratedSubgraphContent.equals(fakeGeneratedSubgraphContent)) {
return getStagingSubgraph(this.chainId)
} else {
return getDevSubgraph(this.chainId)

case TheBadgeSDKEnv.STAGING: // staging subgraph
envGeneratedSubgraphContent = fs.readFileSync('./src/subgraph/staging/generated/subgraph.ts')
if (envGeneratedSubgraphContent.equals(fakeGeneratedSubgraphContent)) {
throw new Error('No staging subgraph')
}
}
} else {
// prod subgraph
const prodGeneratedSubgraphContent = fs.readFileSync('./src/subgraph/staging/generated/subgraph.ts')
if (!prodGeneratedSubgraphContent.equals(fakeGeneratedSubgraphContent)) {
return getStagingSubgraph(this.chainId)

case TheBadgeSDKEnv.PRODUCTION: // prod subgraph
envGeneratedSubgraphContent = fs.readFileSync('./src/subgraph/prod/generated/subgraph.ts')
if (envGeneratedSubgraphContent.equals(fakeGeneratedSubgraphContent)) {
throw new Error('No prod subgraph')
}
return getProdSubgraph(this.chainId)
} else {
throw new Error('No prod subgraph')
}
}
}

private resolveEnv(devMode: boolean, networkConfig: ChainConfig): TheBadgeSDKEnv {
return networkConfig.isTestnet
? devMode
? TheBadgeSDKEnv.DEVELOPMENT
: TheBadgeSDKEnv.STAGING
: TheBadgeSDKEnv.PRODUCTION
}
}
37 changes: 20 additions & 17 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { RPCProvider, SupportedChainsValues, RPCProviderConfig } from '@businessLogic/chains'
import { BadgeStatus } from '@subgraph/prod/generated/subgraph'
import { BadgeStatus as BadgeStatus_DEV } from '@subgraph/dev/generated/subgraph'
import { BadgeStatus as BadgeStatus_STAGING } from '@subgraph/staging/generated/subgraph'
import { BadgeStatus as BadgeStatus_PROD } from '@subgraph/prod/generated/subgraph'
import { Web3Provider } from '@ethersproject/providers'
import { BadgesService } from './services/badges/badges'
import { BadgeModelsService } from './services/badgeModels/badgeModels'
import { UsersService } from './services/users/users'
import { TheBadgeSDKPermissions } from '@businessLogic/sdk/permissions'
import { TheBadgeSDKConfig, TheBadgeSDKConfigOptions } from '@businessLogic/sdk/config'
import { TheBadgeSDKConfig, TheBadgeSDKConfigOptions, TheBadgeSDKEnv } from '@businessLogic/sdk/config'

type BadgeStatus = BadgeStatus_DEV | BadgeStatus_STAGING | BadgeStatus_PROD

class TheBadgeSDK extends TheBadgeSDKConfig {
public readonly badges: BadgesService
Expand Down Expand Up @@ -37,8 +41,10 @@ class TheBadgeSDK extends TheBadgeSDKConfig {
* - rpcProviderConfig provides the configuration for the read only provider: (name, apiKey)
* - name: string (for now only available 'infura' or 'alchemy'),
* - apiKey: string
* - web3Provider is an optional parameter with the web 3 provider to perform write requests to a contract
* - devMode is an optional parameter to use DEV data if the selected chain supports it
* - web3Provider is an optional parameter with the web3 provider to perform write requests to a contract
* - devMode is an @optional boolean parameter to use DEV data if the selected chain supports it:
* - For testnets: if devMode is true, development env data will be used. If false, staging env data will be used.
* - For mainnets: always production env data is used, no matter what value this flag has.
*/
constructor(chainId: SupportedChainsValues, config: TheBadgeSDKConfigOptions) {
super(chainId, config)
Expand All @@ -51,6 +57,7 @@ class TheBadgeSDK extends TheBadgeSDKConfig {

/**
* Get id of the chain used on this instance
*
* @returns number
*/
public getChainId(): SupportedChainsValues {
Expand All @@ -59,6 +66,7 @@ class TheBadgeSDK extends TheBadgeSDKConfig {

/**
* Get the name of the RPC provider (for now only 'infura' and 'alchemy' supported)
*
* @returns RPCProvider
*/
public getRPCProviderName(): RPCProvider {
Expand All @@ -67,14 +75,16 @@ class TheBadgeSDK extends TheBadgeSDKConfig {

/**
* Get the given web3Provider
*
* @returns Web3Provider | undefined
*/
public getWeb3Provider(): Web3Provider | undefined {
return this.web3Provider
}

/**
* Get current permissions, options:
* Get current permissions
*
* @returns READ_ONLY if no web3Provider was given
* @returns READ_AND_WRITE if a web3Provider was given
*/
Expand All @@ -83,22 +93,15 @@ class TheBadgeSDK extends TheBadgeSDKConfig {
}

/**
* Checks if devMode is set.
* Important: this field only has an effect if the selected chain (from given chainId) is a testnet.
*
* For testnets:
* If devMode is true, DEV environment data will be used.
* If devMode is false, QA environment data will be used.
* Get current env
*
* For mainnets (prod env): always production data is used, no matter what value this flag has.
*
* @returns boolean
* @returns TheBadgeSDKEnv (DEVELOPMENT, STAGING or PRODUCTION)
*/
public isDevMode(): boolean {
return this.devMode
public getEnv(): TheBadgeSDKEnv {
return this.env
}
}

export { TheBadgeSDK, RPCProvider, TheBadgeSDKPermissions }
export { TheBadgeSDK, RPCProvider, TheBadgeSDKPermissions, TheBadgeSDKEnv }

export type { TheBadgeSDKConfigOptions, RPCProviderConfig, SupportedChainsValues, BadgeStatus }
11 changes: 7 additions & 4 deletions src/sdk.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { RPCProvider, RPCProviderConfig, TheBadgeSDK, TheBadgeSDKPermissions } from './index'
import { RPCProvider, RPCProviderConfig, TheBadgeSDK, TheBadgeSDKEnv, TheBadgeSDKPermissions } from './index'
import { Web3Provider } from '@ethersproject/providers'
import { SupportedChains } from '@businessLogic/chains'

Expand All @@ -23,13 +23,14 @@ describe('TheBadgeSDK', () => {
const sdk1 = new TheBadgeSDK(5, { rpcProviderConfig: infuraProvider })
expect(sdk1.getChainId()).toBe(5)
expect(sdk1.getRPCProviderName()).toBe(RPCProvider.infura)
expect(sdk1.isDevMode()).toBeFalsy()
expect(sdk1.getEnv()).toBe(TheBadgeSDKEnv.STAGING)
expect(sdk1.getWeb3Provider()).toBeUndefined()
expect(sdk1.getPermissions()).toBe(TheBadgeSDKPermissions.READ_ONLY)

const sdk2 = new TheBadgeSDK(11155111, { rpcProviderConfig: alchemyProvider })
expect(sdk2.getChainId()).toBe(11155111)
expect(sdk2.getRPCProviderName()).toBe(RPCProvider.alchemy)
expect(sdk2.isDevMode()).toBeFalsy()
expect(sdk2.getEnv()).toBe(TheBadgeSDKEnv.STAGING)
expect(sdk2.getWeb3Provider()).toBeUndefined()
expect(sdk2.getPermissions()).toBe(TheBadgeSDKPermissions.READ_ONLY)

Expand All @@ -41,9 +42,11 @@ describe('TheBadgeSDK', () => {
})
expect(sdk3.getChainId()).toBe(5)
expect(sdk3.getRPCProviderName()).toBe(RPCProvider.alchemy)
expect(sdk3.isDevMode()).toBeTruthy()
expect(sdk3.getEnv()).toBe(TheBadgeSDKEnv.DEVELOPMENT)
expect(sdk3.getWeb3Provider()).not.toBeUndefined()
expect(sdk3.getPermissions()).toBe(TheBadgeSDKPermissions.READ_AND_WRITE)

// TODO add test checking init prod sdk when a mainnet chain is available
})

it('should initialize the needed services correctly', () => {
Expand Down
30 changes: 25 additions & 5 deletions src/services/badgeModels/badgeModels.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,32 @@
import {
BadgeModel_Filter,
BadgeModelByIdQuery,
BadgeModelsQuery,
BadgeModelMetadataByIdQuery,
BadgeModel_Filter as BadgeModel_Filter_DEV,
BadgeModelByIdQuery as BadgeModelByIdQuery_DEV,
BadgeModelsQuery as BadgeModelsQuery_DEV,
BadgeModelMetadataByIdQuery as BadgeModelMetadataByIdQuery_DEV,
} from '@subgraph/dev/generated/subgraph'
import {
BadgeModel_Filter as BadgeModel_Filter_STAGING,
BadgeModelByIdQuery as BadgeModelByIdQuery_STAGING,
BadgeModelsQuery as BadgeModelsQuery_STAGING,
BadgeModelMetadataByIdQuery as BadgeModelMetadataByIdQuery_STAGING,
} from '@subgraph/staging/generated/subgraph'
import {
BadgeModel_Filter as BadgeModel_Filter_PROD,
BadgeModelByIdQuery as BadgeModelByIdQuery_PROD,
BadgeModelsQuery as BadgeModelsQuery_PROD,
BadgeModelMetadataByIdQuery as BadgeModelMetadataByIdQuery_PROD,
} from '@subgraph/prod/generated/subgraph'
import { TheBadgeSDKConfig } from '@businessLogic/sdk/config'
import { getFromIPFS } from '@utils/ipfs'
import { MetadataColumn } from '@businessLogic/kleros/types'
import { getFromIPFS } from '@utils/ipfs'

type BadgeModel_Filter = BadgeModel_Filter_DEV | BadgeModel_Filter_STAGING | BadgeModel_Filter_PROD
type BadgeModelByIdQuery = BadgeModelByIdQuery_DEV | BadgeModelByIdQuery_STAGING | BadgeModelByIdQuery_PROD
type BadgeModelsQuery = BadgeModelsQuery_DEV | BadgeModelsQuery_STAGING | BadgeModelsQuery_PROD
type BadgeModelMetadataByIdQuery =
| BadgeModelMetadataByIdQuery_DEV
| BadgeModelMetadataByIdQuery_STAGING
| BadgeModelMetadataByIdQuery_PROD

interface BadgeModelsServiceMethods {
get(searchParams?: { first: number; skip: number; filter?: BadgeModel_Filter }): Promise<BadgeModelsQuery>
Expand Down
101 changes: 83 additions & 18 deletions src/services/badges/badges.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,99 @@
import {
BadgeByBadgeModelIdQuery,
BadgeByIdQuery,
BadgesByUserQuery,
BadgesChallengedQuery,
BadgesInReviewOrChallengedQuery,
BadgesInReviewQuery,
BadgeStatus,
BadgesUserCanReviewQuery,
BadgesOfUserByStatusesQuery,
BadgesNotOfUserByStatusesQuery,
Badge_Filter,
BadgesQuery,
BadgeMetadataByIdQuery,
BadgesMetadataUserHasChallengedQuery,
BadgeByBadgeModelIdQuery as BadgeByBadgeModelIdQuery_DEV,
BadgeByIdQuery as BadgeByIdQuery_DEV,
BadgesByUserQuery as BadgesByUserQuery_DEV,
BadgesChallengedQuery as BadgesChallengedQuery_DEV,
BadgesInReviewOrChallengedQuery as BadgesInReviewOrChallengedQuery_DEV,
BadgesInReviewQuery as BadgesInReviewQuery_DEV,
BadgeStatus as BadgeStatus_DEV,
BadgesUserCanReviewQuery as BadgesUserCanReviewQuery_DEV,
BadgesOfUserByStatusesQuery as BadgesOfUserByStatusesQuery_DEV,
BadgesNotOfUserByStatusesQuery as BadgesNotOfUserByStatusesQuery_DEV,
Badge_Filter as Badge_Filter_DEV,
BadgesQuery as BadgesQuery_DEV,
BadgeMetadataByIdQuery as BadgeMetadataByIdQuery_DEV,
BadgesMetadataUserHasChallengedQuery as BadgesMetadataUserHasChallengedQuery_DEV,
} from '@subgraph/dev/generated/subgraph'
import {
BadgeByBadgeModelIdQuery as BadgeByBadgeModelIdQuery_STAGING,
BadgeByIdQuery as BadgeByIdQuery_STAGING,
BadgesByUserQuery as BadgesByUserQuery_STAGING,
BadgesChallengedQuery as BadgesChallengedQuery_STAGING,
BadgesInReviewOrChallengedQuery as BadgesInReviewOrChallengedQuery_STAGING,
BadgesInReviewQuery as BadgesInReviewQuery_STAGING,
BadgeStatus as BadgeStatus_STAGING,
BadgesUserCanReviewQuery as BadgesUserCanReviewQuery_STAGING,
BadgesOfUserByStatusesQuery as BadgesOfUserByStatusesQuery_STAGING,
BadgesNotOfUserByStatusesQuery as BadgesNotOfUserByStatusesQuery_STAGING,
Badge_Filter as Badge_Filter_STAGING,
BadgesQuery as BadgesQuery_STAGING,
BadgeMetadataByIdQuery as BadgeMetadataByIdQuery_STAGING,
BadgesMetadataUserHasChallengedQuery as BadgesMetadataUserHasChallengedQuery_STAGING,
} from '@subgraph/staging/generated/subgraph'
import {
BadgeByBadgeModelIdQuery as BadgeByBadgeModelIdQuery_PROD,
BadgeByIdQuery as BadgeByIdQuery_PROD,
BadgesByUserQuery as BadgesByUserQuery_PROD,
BadgesChallengedQuery as BadgesChallengedQuery_PROD,
BadgesInReviewOrChallengedQuery as BadgesInReviewOrChallengedQuery_PROD,
BadgesInReviewQuery as BadgesInReviewQuery_PROD,
BadgeStatus as BadgeStatus_PROD,
BadgesUserCanReviewQuery as BadgesUserCanReviewQuery_PROD,
BadgesOfUserByStatusesQuery as BadgesOfUserByStatusesQuery_PROD,
BadgesNotOfUserByStatusesQuery as BadgesNotOfUserByStatusesQuery_PROD,
Badge_Filter as Badge_Filter_PROD,
BadgesQuery as BadgesQuery_PROD,
BadgeMetadataByIdQuery as BadgeMetadataByIdQuery_PROD,
BadgesMetadataUserHasChallengedQuery as BadgesMetadataUserHasChallengedQuery_PROD,
} from '@subgraph/prod/generated/subgraph'
import { ContractTransaction } from 'ethers'
import { TheBadgeSDKConfig } from '@businessLogic/sdk/config'
import { getFromIPFS } from '@utils/ipfs'
import { MetadataColumn } from '@businessLogic/kleros/types'
import { BadgeModelMetadata } from '@businessLogic/theBadge/BadgeMetadata'
import { BackendFileResponse } from '@businessLogic/types'
import { getFromIPFS } from '@utils/ipfs'
import {
createAndUploadBadgeEvidence,
createAndUploadBadgeMetadata,
createEvidencesValuesObject,
encodeIpfsEvidence,
} from '@utils/badges/mintHelpers'
import { BadgeModelMetadata } from '@businessLogic/theBadge/BadgeMetadata'
import { KlerosListStructure } from '@utils/kleros/generateKlerosListMetaEvidence'
import { BackendFileResponse } from '@businessLogic/types'
import { ContractTransaction } from 'ethers'
import { schemaFactory } from '@utils/zod/validators'

type BadgeByBadgeModelIdQuery =
| BadgeByBadgeModelIdQuery_DEV
| BadgeByBadgeModelIdQuery_STAGING
| BadgeByBadgeModelIdQuery_PROD
type BadgeByIdQuery = BadgeByIdQuery_DEV | BadgeByIdQuery_STAGING | BadgeByIdQuery_PROD
type BadgesByUserQuery = BadgesByUserQuery_DEV | BadgesByUserQuery_STAGING | BadgesByUserQuery_PROD
type BadgesChallengedQuery = BadgesChallengedQuery_DEV | BadgesChallengedQuery_STAGING | BadgesChallengedQuery_PROD
type BadgesInReviewOrChallengedQuery =
| BadgesInReviewOrChallengedQuery_DEV
| BadgesInReviewOrChallengedQuery_STAGING
| BadgesInReviewOrChallengedQuery_PROD
type BadgesInReviewQuery = BadgesInReviewQuery_DEV | BadgesInReviewQuery_STAGING | BadgesInReviewQuery_PROD
type BadgeStatus = BadgeStatus_DEV | BadgeStatus_STAGING | BadgeStatus_PROD
type BadgesUserCanReviewQuery =
| BadgesUserCanReviewQuery_DEV
| BadgesUserCanReviewQuery_STAGING
| BadgesUserCanReviewQuery_PROD
type BadgesOfUserByStatusesQuery =
| BadgesOfUserByStatusesQuery_DEV
| BadgesOfUserByStatusesQuery_STAGING
| BadgesOfUserByStatusesQuery_PROD
type BadgesNotOfUserByStatusesQuery =
| BadgesNotOfUserByStatusesQuery_DEV
| BadgesNotOfUserByStatusesQuery_STAGING
| BadgesNotOfUserByStatusesQuery_PROD
type Badge_Filter = Badge_Filter_DEV | Badge_Filter_STAGING | Badge_Filter_PROD
type BadgesQuery = BadgesQuery_DEV | BadgesQuery_STAGING | BadgesQuery_PROD
type BadgeMetadataByIdQuery = BadgeMetadataByIdQuery_DEV | BadgeMetadataByIdQuery_STAGING | BadgeMetadataByIdQuery_PROD
type BadgesMetadataUserHasChallengedQuery =
| BadgesMetadataUserHasChallengedQuery_DEV
| BadgesMetadataUserHasChallengedQuery_STAGING
| BadgesMetadataUserHasChallengedQuery_PROD

interface BadgesServiceMethods {
get(searchParams?: { first: number; skip: number; filter?: Badge_Filter }): Promise<BadgesQuery>
getById(badgeId: string): Promise<BadgeByIdQuery>
Expand Down
Loading

0 comments on commit 42598df

Please sign in to comment.