Skip to content

Commit

Permalink
mongo
Browse files Browse the repository at this point in the history
  • Loading branch information
xlc committed Aug 21, 2022
1 parent bcbb7c9 commit 7e4ec39
Show file tree
Hide file tree
Showing 7 changed files with 758 additions and 3 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"dotenv": "^16.0.1",
"graphql-request": "^4.3.0",
"moment": "^2.29.4",
"mongoose": "^6.5.2",
"rxjs": "^7.5.6",
"yargs": "^17.5.1"
},
Expand Down
81 changes: 81 additions & 0 deletions src/mongo/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
export const mongodbUrl = 'mongodb://localhost:27017/db'

const calcDexSharePrice = (val1: bigint, val2: bigint, total: bigint, decimals: bigint) => {
return Number((10n ** decimals * val1) / val2) / Number(total)
}

export const tokens = {
'{"DexShare":[{"Token":"ACA"},{"Token":"AUSD"}]}': {
decimals: 12,
price: calcDexSharePrice(3198041192196843092n, 961142132589918007n, 2686314952009514069n, 12n),
},
'{"DexShare":[{"Token":"AUSD"},{"ForeignAsset":3}]}': {
decimals: 12,
price: calcDexSharePrice(133779256694784484n, 11179554822080479n, 149418353799999999n, 12n),
},
'{"DexShare":[{"Token":"AUSD"},{"ForeignAsset":4}]}': {
decimals: 12,
price: calcDexSharePrice(74709176900000000n, 288379511n, 243821296627833529n, 12n),
},
'{"DexShare":[{"Token":"AUSD"},{"LiquidCrowdloan":13}]}': {
decimals: 12,
price: calcDexSharePrice(1162765061520352282n, 1697757504904459n, 3017879558819282474n, 12n),
},
'{"DexShare":[{"Token":"AUSD"},{"Token":"LDOT"}]}': {
decimals: 12,
price: calcDexSharePrice(683903178710475218n, 6991400067299826n, 1837762527784655358n, 12n),
},
'{"DexShare":[{"Token":"DOT"},{"LiquidCrowdloan":13}]}': {
decimals: 10,
price: calcDexSharePrice(683903178710475218n, 6991400067299826n, 4299384396226919n, 10n),
},
'{"ForeignAsset":0}': {
// GLMR
decimals: 18,
price: 0, // ignored
},
'{"ForeignAsset":1}': {
// PARA
decimals: 12,
price: 0, // ignored
},
'{"ForeignAsset":2}': {
// ASTAR
decimals: 18,
price: 0, //ignored
},
'{"ForeignAsset":3}': {
// iBTC
decimals: 8,
price: 24319.33,
},
'{"ForeignAsset":4}': {
// INTR
decimals: 10,
price: 0.1187,
},
'{"LiquidCrowdloan":13}': {
decimals: 10,
price: 6.72,
},
'{"StableAssetPoolToken":0}': {
decimals: 10,
price: 8.96,
},
'{"Token":"ACA"}': {
decimals: 12,
price: 0.2785,
},
'{"Token":"AUSD"}': {
decimals: 12,
price: 1,
},
'{"Token":"DOT"}': {
decimals: 10,
price: 8.96,
},
'{"Token":"LDOT"}': {
decimals: 10,
price: 0.984,
},
} as Record<string, { decimals: number; price: number }>
100 changes: 100 additions & 0 deletions src/mongo/models.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { Decimal128, Schema, model } from 'mongoose'

export interface Meta {
block: number
traceBlock: number
}

export const metaSchema = new Schema<Meta>({
block: Number,
traceBlock: Number,
})

export const Meta = model('Meta', metaSchema)

export interface Event {
_id: string
height: number
blockHash: string
extrinsicHash?: string
call?: string
event: string
amount: Decimal128
currencyId: string
from?: string
to?: string
who?: string
}

export const eventSchema = new Schema<Event>({
_id: String,
height: Number,
blockHash: String,
extrinsicHash: String,
call: String,
event: String,
amount: Schema.Types.Decimal128,
currencyId: String,
from: String,
to: String,
who: String,
})

export const Event = model('Event', eventSchema)

export interface Trace {
_id: string // event id
amount: Decimal128
currencyId: string
from: string
to: string
value: number
}

export const traceSchema = new Schema<Trace>({
_id: String,
amount: Schema.Types.Decimal128,
currencyId: String,
from: String,
to: String,
value: Number,
})

export const Trace = model('Trace', traceSchema)

export interface AccountTrace {
_id: string // address + event id
height: number
blockHash: string
extrinsicHash?: string
call?: string
event: string
account: string // address
eventId: string // event id
amount: Decimal128
currencyId: string
category: string
value: number
}

export const accountTraceSchema = new Schema<AccountTrace>({
_id: String,
height: Number,
blockHash: String,
extrinsicHash: String,
call: String,
event: String,
account: String,
eventId: String,
amount: Schema.Types.Decimal128,
currencyId: String,
category: String,
value: Number,
})

export const AccountTrace = model('AccountTrace', accountTraceSchema)

export interface AccountBalance {
_id: string // address
value: number
}
78 changes: 78 additions & 0 deletions src/mongo/query.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/* eslint-disable @typescript-eslint/no-unsafe-return */

import { encodeAddress } from '@polkadot/keyring'
import { gql, request } from 'graphql-request'

const url = 'https://acala.explorer.subsquid.io/graphql'
const ss58Prefix = 10

export const getLatestBlockHeight = async () => {
const query = gql`
query {
blocks(limit: 1, orderBy: height_DESC) {
height
}
}
`

const { blocks } = await request(url, query)

return blocks[0].height as number
}

const processValue = (value: any): any => {
if (Array.isArray(value)) {
return value.map(processValue) as any
}
if (typeof value === 'object') {
if ('value' in value) {
return { [value.__kind]: processValue(value.value) }
}
return value.__kind
}
return value
}

export const queryEvents = async (fromBlock: number, toBlock: number) => {
const query = gql`
query q($fromBlock: Int, $toBlock: Int) {
events(
where: {
block: { height_gte: $fromBlock, height_lt: $toBlock }
call: { success_eq: true }
AND: { name_startsWith: "Tokens", OR: { name_startsWith: "Balances" } }
}
) {
extrinsic {
hash
}
block {
height
hash
}
call {
name
}
args
name
id
}
}
`

const { events } = await request(url, query, { fromBlock, toBlock })

return (events as any[]).map((x: any) => ({
_id: x.id,
height: x.block.height,
blockHash: x.block.hash,
extrinsicHash: x.extrinsic?.hash,
call: x.call?.name,
event: x.name,
amount: x.args.amount,
currencyId: JSON.stringify(x.args.currencyId ? processValue(x.args.currencyId) : { Token: 'ACA' }),
from: x.args.from && encodeAddress(x.args.from, ss58Prefix),
to: x.args.to && encodeAddress(x.args.to, ss58Prefix),
who: x.args.who && encodeAddress(x.args.who, ss58Prefix),
}))
}
61 changes: 61 additions & 0 deletions src/mongo/scripts/query-acc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import * as config from '../config'
import { AccountTrace } from '../models'
import { formatBalance, table } from '../../log'
import mongoose from 'mongoose'

const main = async () => {
await mongoose.connect(config.mongodbUrl)

const agg = [
{
$group: {
_id: ['$account', '$category', '$currencyId'],
sum: {
$sum: '$amount',
},
},
},
]

const sum = {} as Record<string, Record<string, Record<string, bigint>>>
for await (const data of AccountTrace.aggregate(agg)) {
const acc = data._id[0]
const category = data._id[1]
const currencyId = data._id[2]

if (!sum[acc]) {
sum[acc] = {}
}

if (!sum[acc][category]) {
sum[acc][category] = {}
}

if (!sum[acc][category][currencyId]) {
sum[acc][category][currencyId] = 0n
}

sum[acc][category][currencyId] += BigInt(data.sum.toString())
}

const res = [] as { acc: string; category: string; token: string; amount: string }[]

for (const [addr, values] of Object.entries(sum)) {
for (const [category, currencies] of Object.entries(values)) {
for (const [currencyId, amount] of Object.entries(currencies)) {
res.push({
acc: addr,
category,
token: currencyId,
amount: formatBalance(amount, config.tokens[currencyId].decimals),
})
}
}
}

table(res)

await mongoose.disconnect()
}

main().catch(console.error)
Loading

0 comments on commit 7e4ec39

Please sign in to comment.