UNPKG

@chorus-one/ethereum

Version:

All-in-one toolkit for building staking dApps on Ethereum network

119 lines (109 loc) 3.96 kB
import { createPublicClient, PublicClient, http, Hex, Chain } from 'viem' import { hoodi, mainnet } from 'viem/chains' import { Networks } from './types/networks' // Represents a single request to a graphql backend export interface GraphQLRequest { type: 'api' | 'graph' op: string query: string // eslint-disable-next-line @typescript-eslint/no-explicit-any variables: any } // Connector abstraction, providing on-chain and GraphQL API primitives export class StakewiseConnector { chain: Chain /** Base URL for Stakewise main graph API */ baseAPI: string /** Base URL for Stakewise subgraph */ baseGraph: string /** Web3 connector for calling read-only contract methods */ eth: PublicClient /** Stakewise keeper contract address */ keeper: Hex /** Stakewise price oracle contract address */ priceOracle: Hex /** Stakewise mint token controller contract address */ mintTokenController: Hex constructor (network: Networks, rpcUrl?: string) { // These parameters might need to be changed for Gnosis and Mainnet const transport = rpcUrl ? http(rpcUrl) : http() switch (network) { case 'hoodi': this.chain = hoodi this.eth = createPublicClient({ chain: hoodi, transport }) this.baseAPI = 'https://hoodi-api.stakewise.io/graphql' this.baseGraph = 'https://graphs.stakewise.io/hoodi/subgraphs/name/stakewise/prod' // Reference: https://docs.stakewise.io/for-developers/networks/hoodi this.keeper = '0xA7D1Ac9D6F32B404C75626874BA56f7654c1dC0f' this.priceOracle = '0xe8a222D887b468a71Ee8a27df4fa3b886A4B7BA1' this.mintTokenController = '0x140Fc69Eabd77fFF91d9852B612B2323256f7Ac1' break case 'ethereum': this.chain = mainnet this.eth = createPublicClient({ chain: mainnet, transport }) this.baseAPI = 'https://mainnet-api.stakewise.io/graphql' this.baseGraph = 'https://graphs.stakewise.io/mainnet-b/subgraphs/name/stakewise/prod' // Reference: https://docs.stakewise.io/for-developers/networks/mainnet this.keeper = '0x6B5815467da09DaA7DC83Db21c9239d98Bb487b5' this.priceOracle = '0x8023518b2192FB5384DAdc596765B3dD1cdFe471' this.mintTokenController = '0x2A261e60FB14586B474C208b1B7AC6D0f5000306' break default: throw new Error(`Invalid network passed: ${network}`) } } // Perform graphQL request graphqlRequest = async (request: GraphQLRequest): Promise<{ data: any }> => { const body: string = JSON.stringify({ operationName: request.op, query: request.query.trim(), variables: request.variables }) const params: RequestInit = { method: 'POST', headers: { 'Content-Type': 'application/json; charset=utf-8', Accept: '*/*' }, body } let uri: string switch (request.type) { case 'api': uri = this.baseAPI break case 'graph': uri = this.baseGraph break default: throw new Error(`Invalid request type: ${request.type}`) } const endpoint = `${uri}?opName=${request.op}` const response = await fetch(endpoint, params) if (!response.ok) { throw new Error(`Invalid response from Stakewise. Endpoint: ${endpoint}`) } const responseData = await response.json() if (typeof responseData !== 'object' || responseData === null) { throw new Error('Invalid response from Stakewise') } if ( 'errors' in responseData && responseData.errors && Array.isArray(responseData.errors) && responseData.errors.length ) { throw new Error(responseData.errors[0].message) } if (!('data' in responseData) || typeof responseData.data !== 'object' || !responseData.data) { throw new Error('Response from Stakewise is missing data') } return responseData } }