Skip to content
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
1 change: 1 addition & 0 deletions dev.env
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ DB_PORT=23798
GQL_PORT=4350
# JSON-RPC node endpoint, both wss and https endpoints are accepted
RPC_ENDPOINT=## Fill me in! ##
RPC_BACKUP=## Backup RPC endpoint incase the primary is down ##
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"js-yaml": "^4.1.0",
"lodash": "^4.17.21",
"pg": "^8.11.0",
"reflect-metadata": "^0.1.14",
"type-graphql": "^1.2.0-rc.1",
"typeorm": "^0.3.16",
"uuid": "^9.0.0",
Expand Down
2 changes: 1 addition & 1 deletion squid.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ deploy:
secrets:
- RPC_ENDPOINT
- RPC_ENDPOINT_999
- RPC_BACKUP
processor:
# cmd: [ "node", "lib/main" ]
# env:
Expand Down Expand Up @@ -44,4 +45,3 @@ deploy:
- '1000'
scale:
dedicated: true

112 changes: 112 additions & 0 deletions src/server-extension/ogn-stats.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { GraphQLResolveInfo } from 'graphql'
import 'reflect-metadata'
import { Field, Info, ObjectType, Query, Resolver } from 'type-graphql'
import type { EntityManager } from 'typeorm'
import {
createPublicClient,
fallback,
formatEther,
getContract,
http,
parseAbi,
} from 'viem'
import { mainnet } from 'viem/chains'

import * as Erc20ABI from '../abi/erc20.abi'
import { OGN_ADDRESS } from '../utils/addresses'

const publicClient = createPublicClient({
chain: mainnet,
transport: fallback([
http(process.env.RPC_ENDPOINT),
http(process.env.RPC_BACKUP),
]),
})

const ogn = getContract({
address: OGN_ADDRESS,
abi: Erc20ABI.ABI_JSON,
publicClient,
})

@ObjectType()
export class OGNStatsResult {
@Field(() => Number, { nullable: false })
circulatingSupply!: number

@Field(() => Number, { nullable: false })
totalSupply!: number

constructor(props: Partial<OGNStatsResult>) {
Object.assign(this, props)
}
}

@Resolver()
export class OGNStatsResolver {
constructor(private tx: () => Promise<EntityManager>) {}

@Query(() => OGNStatsResult)
async ognStats(@Info() info: GraphQLResolveInfo): Promise<OGNStatsResult> {
const result = new OGNStatsResult({})
const fields = info.fieldNodes[0].selectionSet?.selections.map(
(selection) => (selection as any).name.value,
)

// Only fetch the fields that are requested
if (fields?.includes('circulatingSupply')) {
result.circulatingSupply = await getCirculatingSupply()
}
if (fields?.includes('totalSupply')) {
result.totalSupply = await getTotalSupply()
}

return result
}
}

async function getCirculatingSupply(): Promise<number> {
const excludeBalance = [
'0xe011fa2a6df98c69383457d87a056ed0103aa352', // foundation_reserve
'0xbe2ab3d3d8f6a32b96414ebbd865dbd276d3d899', // new_foundation_reserve
'0xcaa5ef7abc36d5e5a3e4d7930dcff3226617a167', // team_dist
'0x2eae0cae2323167abf78462e0c0686865c67a655', // new_team_dist
'0x3da5045699802ea1fcc60130dedea67139c5b8c0', // investor_dist
'0xfe730b3cf80ca7b31905f70241f7c786baf443e3', // new_investor_dist
'0x1a34e5b97d684b124e32bd3b7dc82736c216976b', // dist_staging
'0x12d7ef3c933d091210cd931224ead45d9cfddde0', // new_dist_staging
'0xbc0722eb6e8ba0217aeea5694fe4f214d2e53017', // partnerships
'0x2d00c3c132a0567bbbb45ffcfd8c6543e08ff626', // ecosystem_growth
'0x8ac3b96d118288427055ae7f62e407fc7c482f57', // brave_endeavors
'0xa2cc2eae69cbf04a3d5660bc3e689b035324fc3f', // limitless_alpha
]

const abi = parseAbi([
'function balanceOf(address owner) view returns (uint256)',
'function totalSupply() view returns (uint256)',
])

const contractCalls = [
{ address: OGN_ADDRESS, abi, functionName: 'totalSupply' },
...excludeBalance.map((addr) => ({
address: OGN_ADDRESS,
abi,
functionName: 'balanceOf',
args: [addr],
})),
] as never

const balances = await publicClient.multicall({ contracts: contractCalls })

const circulatingSupply = balances.slice(1).reduce((m, o) => {
if (o.status !== 'success') return m
return (m -= o.result as bigint)
}, balances[0].result as bigint)

return Number(formatEther(circulatingSupply))
}

async function getTotalSupply(): Promise<number> {
const totalSupply = (await ogn.read.totalSupply()) as bigint
return Number(formatEther(totalSupply))
}
1 change: 1 addition & 0 deletions src/server-extension/resolvers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { OGNStatsResolver } from '../ogn-stats'
1 change: 1 addition & 0 deletions src/utils/addresses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export const AURA_REWARDS_POOL_ADDRESS =

export const GOVERNANCE_ADDRESS = '0x3cdd07c16614059e66344a7b579dab4f9516c0b6'

export const OGN_ADDRESS = '0x8207c1ffc5b6804f6024322ccf34f29c3541ae26'
export const OGV_ADDRESS = '0x9c354503c38481a7a7a51629142963f98ecc12d0'

export const VEOGV_ADDRESS = '0x0c4576ca1c365868e162554af8e385dc3e7c66d9'
Loading