Skip to content

Commit

Permalink
feat: sync member wallets
Browse files Browse the repository at this point in the history
  • Loading branch information
JounQin committed Feb 15, 2020
1 parent 349e33e commit 53fd66f
Show file tree
Hide file tree
Showing 3 changed files with 293 additions and 218 deletions.
14 changes: 7 additions & 7 deletions package.json
Expand Up @@ -57,21 +57,21 @@
"vue": "^2.6.11",
"vue-qrcode": "^0.3.3",
"vue-router": "^3.1.5",
"vuetify": "^2.2.11",
"vuetify": "^2.2.12",
"vuex": "^3.1.2"
},
"devDependencies": {
"@1stg/app-config": "^0.4.1",
"@1stg/tslint-config": "^0.8.1",
"@1stg/app-config": "^0.4.2",
"@1stg/tslint-config": "^0.8.2",
"@d-ts/vue": "^0.4.2",
"@nuxt/types": "^0.6.1",
"@nuxt/typescript-build": "^0.5.6",
"@nuxt/typescript-runtime": "^0.3.8",
"@nuxtjs/eslint-config-typescript": "^1.0.2",
"@pkgr/rollup": "^0.10.0",
"@pkgr/rollup": "^0.10.2",
"@types/clipboard": "^2.0.1",
"@types/http-proxy": "^1.17.3",
"@types/koa": "^2.11.0",
"@types/koa": "^2.11.1",
"@types/koa-bodyparser": "^4.3.0",
"@types/koa-compress": "^2.0.9",
"@types/koa-logger": "^3.1.1",
Expand All @@ -85,7 +85,7 @@
"@types/webpack-env": "^1.15.1",
"babel-preset-vca-jsx": "^0.3.4",
"consola": "^2.11.3",
"cpy-cli": "^3.0.0",
"cpy-cli": "^3.1.0",
"dotenv": "^8.2.0",
"env-cmd": "^10.1.0",
"eslint-config-vuetify": "^0.5.0",
Expand All @@ -105,7 +105,7 @@
"resolutions": {
"@babel/core": "^7.8.4",
"@babel/preset-env": "^7.8.4",
"@types/node": "^13.7.0",
"@types/node": "^13.7.1",
"eslint-plugin-prettier": "^3.1.2",
"imagemin-gifsicle": "^6.0.1"
},
Expand Down
227 changes: 149 additions & 78 deletions server/utils/helpers.ts
Expand Up @@ -3,14 +3,14 @@ import { Octokit } from '@octokit/rest'
import { BinaryLike, createHash, randomBytes } from 'crypto'
import { formatRFC3339 } from 'date-fns'
import { last, uniqBy } from 'lodash'
import { bignumber } from 'mathjs'
import { bignumber, isPositive } from 'mathjs'
import { Asset } from 'mixin-node-sdk'
import { Connection, createConnection } from 'typeorm'

import { filterAssets } from '@/utils'
import { DonationDistribution, filterAssets } from '@/utils'

import * as entities from '../entities'
import { Bot, Transaction, Wallet } from '../entities'
import { Bot, Member, MemberWallet, Transaction, Wallet } from '../entities'

import { mixin } from './constants'
import { mixinBot } from './mixin'
Expand Down Expand Up @@ -82,94 +82,165 @@ export const getAssets = (() => {
}
})()

// eslint-disable-next-line sonarjs/cognitive-complexity
export const syncTransactions = async (projectId?: string) => {
const [conn, assets] = await Promise.all([getConn(), getAssets()])
const bots = await conn.getRepository(Bot).find(
const queryRunner = conn.createQueryRunner()
await queryRunner.connect()
const { manager } = queryRunner

const bots = await manager.find(
Bot,
projectId && {
where: {
projectId,
},
},
)
const walletRepo = conn.getRepository(Wallet)
const transactionRepo = conn.getRepository(Transaction)

return Promise.all(
bots.map(bot => {
const botMixin = mixinBot(bot)
return Promise.all(
assets.map(async asset => {
const wallet = await walletRepo.findOneOrFail({
where: {
botId: bot.id,
assetId: asset.asset_id,
},
})

let snapshots = await botMixin.query_network_snapshots({
asset: asset.asset_id,
offset: formatRFC3339(wallet.syncedAt || wallet.createdAt),
order: 'ASC',
})

let allSnapshots = snapshots

while (snapshots.length >= 500) {
const lastSnapshot = last(snapshots)
snapshots = await botMixin.query_network_snapshots({

await queryRunner.startTransaction()

try {
await Promise.all(
// eslint-disable-next-line sonarjs/cognitive-complexity
bots.map(bot => {
const { id: botId, projectId } = bot
const botMixin = mixinBot(bot)

let members: Member[]

return Promise.all(
assets.map(async asset => {
const { asset_id: assetId } = asset
const wallet = await manager.findOneOrFail(Wallet, {
where: {
botId,
assetId,
},
})

let snapshots = await botMixin.query_network_snapshots({
asset: asset.asset_id,
offset: lastSnapshot.created_at,
offset: formatRFC3339(wallet.syncedAt || wallet.createdAt),
order: 'ASC',
})

const nextSnapshots = uniqBy(
allSnapshots.concat(snapshots),
'snapshot_id',
)
let allSnapshots = snapshots

if (nextSnapshots.length === allSnapshots.length) {
break
while (snapshots.length >= 500) {
const lastSnapshot = last(snapshots)
snapshots = await botMixin.query_network_snapshots({
asset: asset.asset_id,
offset: lastSnapshot.created_at,
order: 'ASC',
})

const nextSnapshots = uniqBy(
allSnapshots.concat(snapshots),
'snapshot_id',
)

if (nextSnapshots.length === allSnapshots.length) {
break
}
allSnapshots = nextSnapshots
}
allSnapshots = nextSnapshots
}

const transactions = await transactionRepo.save(
allSnapshots
.filter(s => s.user_id)
.map(s => ({
id: s.snapshot_id,
projectId: bot.projectId,
botId: bot.id,
assetId: asset.asset_id,
amount: Number(s.amount),
createdAt: s.created_at,
sender: s.user_id,
})),
)

const { total, balance } = transactions.reduce(
(acc, { amount }) => {
acc.balance = acc.balance.add(amount)
if (amount > 0) {
acc.total = acc.total.add(amount)

const transactions = await manager.save(
allSnapshots
.filter(s => s.user_id)
.map(s =>
Object.assign(new Transaction(), {
id: s.snapshot_id,
projectId,
botId,
assetId,
amount: Number(s.amount),
createdAt: s.created_at,
sender: s.user_id,
}),
),
)

const { total, balance } = transactions.reduce(
(acc, { amount }) => {
acc.balance = acc.balance.add(amount)
if (amount > 0) {
acc.total = acc.total.add(amount)
}
return acc
},
{
total: bignumber(0),
balance: bignumber(0),
},
)

if (isPositive(total)) {
members =
members ||
(members = await manager.find(Member, {
where: {
projectId,
},
}))

const memberWallets = await manager.find(MemberWallet, {
where: {
projectId,
botId,
assetId,
},
})

let newMemberWallets: MemberWallet[]

// eslint-disable-next-line sonarjs/no-small-switch
switch (bot.distribution) {
case DonationDistribution.IdenticalAmount: {
const amount = total.dividedBy(members.length)
newMemberWallets = members.map(m => {
const memberWallet =
memberWallets.find(({ userId }) => m.userId === userId) ||
Object.assign(new MemberWallet(), {
projectId,
botId: bot.id,
assetId,
userId: m.userId,
total: 0,
balance: 0,
})

memberWallet.total = amount
.add(memberWallet.total)
.toNumber()
memberWallet.balance = amount
.add(memberWallet.balance)
.toNumber()

return memberWallet
})
break
}
}
return acc
},
{
total: bignumber(0),
balance: bignumber(0),
},
)

return walletRepo.save(
Object.assign(wallet, {
total: total.add(wallet.total).toNumber(),
balance: balance.add(wallet.balance).toNumber(),
syncedAt: last(allSnapshots)?.created_at,
}),
)
}),
)
}),
)

manager.save(newMemberWallets)
}

return manager.save(
Object.assign(wallet, {
total: total.add(wallet.total).toNumber(),
balance: balance.add(wallet.balance).toNumber(),
syncedAt: last(allSnapshots)?.created_at,
}),
)
}),
)
}),
)
} catch {
await queryRunner.rollbackTransaction()
} finally {
await queryRunner.release()
}
}

0 comments on commit 53fd66f

Please sign in to comment.