Skip to content

Instantly share code, notes, and snippets.

@witoldsz
Created December 28, 2018 18:20
Show Gist options
  • Save witoldsz/1ce270046d6d531eb939c24870bbcb60 to your computer and use it in GitHub Desktop.
Save witoldsz/1ce270046d6d531eb939c24870bbcb60 to your computer and use it in GitHub Desktop.
Semux Pool calc (concept)
const DELEGATE_ADDR = '0x…'
const TXS_URL = `https://semux.online/v2.1.0/account/transactions?address=${DELEGATE_ADDR}&from=${0}&to=99999`
const BURNED_SEM_OWNER = shortHash('0x…')
const BURNED_SEM_PAID_DATE = new Date('2018-10-15T00:00:00Z')
const IGNORE_ADDR = '0x…'
const ALIASES = {
'xyz1': '🔜',
'xyz2': '🐋',
'xyz3': '💎',
'xyz4': 'WS',
}
async function main() {
const txs = await fetchTxs()
const initialState = {
stakes: {}, // { owner1: semAmount }, { owner2: semAmount }, …}
gains: {}, // { owner1: semAmount }, { owner2: semAmount }, …}
}
const finalState = txs
.reduce((state, tx) => (
isVoteIn(tx) ? voteAction(state, tx, 1)
: isVoteOut(tx) ? voteAction(state, tx, -1)
: isProfitOut(tx) ? profitOutAction(state, tx)
: isSelfVote(tx) ? selfVoteAction(state, tx)
: state
), initialState)
return {
stakesSum: Math.round($objSumValues(finalState.stakes)),
gainsSum: Math.round($objSumValues(finalState.gains)),
stakes: roundValues(finalState.stakes),
gains: roundValues(finalState.gains),
}
}
main().then(console.log, console.warn)
// ---------------------------------------------------------------
// actions
function voteAction(state, tx, multiplier/* in=1 out=-1**/) {
const owner = shortHash(tx.from)
const amount = nanoToSem(tx.value) * multiplier
const icon = amount > 0 ? '📥' : '📤'
const newStakes = $updateKey(owner, (oldVal) => (oldVal || 0) + amount, state.stakes)
const newGains = $updateKey(owner, (oldVal) => (oldVal || 0), state.gains)
console.log(`${showDate(tx)},${icon},${showAmount(amount)},${showAddr(owner)},${showStakesAndGains(newStakes, newGains)}`)
return { ...state, stakes: newStakes, gains: newGains }
}
function profitOutAction(state, tx) {
const recipient = shortHash(tx.to)
const amount = nanoToSem(tx.value)
const newStakes = $updateKey(recipient, (oldVal) => oldVal - amount, state.stakes)
const newGains = $updateKey(recipient, (oldVal) => oldVal - amount, state.gains)
console.log(`${showDate(tx)},💰,${showAmount(amount)},${showAddr(recipient)}`)
return { ...state, stakes: newStakes, gains: newGains }
}
function selfVoteAction(state, tx) {
const amount = nanoToSem(tx.value)
const oldStakes = state.stakes
const totalStake = totalStakeOf(oldStakes, tx)
const gainOf_ = (owner, stake) => gainOf(totalStake, tx, owner, stake)
const newStakes = $mapObj(
({ key: owner, val: stake }) => stake + gainOf_(owner, stake),
oldStakes
)
const newGains = $mapObj(
({ key: owner, val }) => val + gainOf_(owner, oldStakes[owner]),
state.gains
)
console.log(`${showDate(tx)},🌟,${showAmount(amount)},··,${showStakesAndGains(newStakes, newGains)}`)
return { ...state, stakes: newStakes, gains: newGains }
}
function isVoteIn(tx) {
return tx.type === 'VOTE'
&& tx.from !== DELEGATE_ADDR
&& tx.from !== IGNORE_ADDR
&& tx.to === DELEGATE_ADDR
}
function isVoteOut(tx) {
return tx.type === 'UNVOTE'
&& tx.from !== DELEGATE_ADDR
&& tx.from !== IGNORE_ADDR
&& tx.to === DELEGATE_ADDR
}
function isProfitOut(tx) {
return tx.type === 'TRANSFER'
&& tx.from === DELEGATE_ADDR
&& tx.to !== DELEGATE_ADDR
}
function isSelfVote(tx) {
return tx.type === 'VOTE'
&& tx.from === DELEGATE_ADDR
&& tx.to === DELEGATE_ADDR
}
// ---------------------------------------------------------------
// utils
function totalStakeOf(stakes, tx) {
return $objSumValues(stakes) + (dateOf(tx) < BURNED_SEM_PAID_DATE ? 1000 : 0)
}
function gainOf(totalStake, tx, owner, stake_) {
const amount = nanoToSem(tx.value)
const stake = stake_ + (owner === BURNED_SEM_OWNER && dateOf(tx) < BURNED_SEM_PAID_DATE ? 1000 : 0)
return stake * amount / totalStake
}
function roundValues(obj) {
return $mapObj(({ val }) => Math.round(val), obj)
}
async function fetchTxs() {
const a = await fetch(TXS_URL)
const b = await a.json()
return b.result
}
function dateOf(tx) {
return new Date(parseInt(tx.timestamp))
}
function showDate(tx) {
return dateOf(tx).toISOString().substr(0, 10)
}
function showAddr(a) {
return ALIASES[a] || a
}
function showAmount(a, minDigits = 5, padSide = 'left') {
const pad = str => str.length >= minDigits ? str : pad(padSide === 'left' ? ` ${str}` : `${str} `)
return pad(`${a | 0}`)
}
function showAmounts(obj) {
return `"{ ${Object.keys(obj).map((k) => `${showAddr(k)}:${showAmount(obj[k])}`).join(',') } }"`
}
function showStakesAndGains(stakes, gains) {
const amounts = (key) => `${showAmount(stakes[key])}﹩${showAmount(gains[key], 4, 'right')}`
return Object.keys(stakes).map((k) => `${showAddr(k)}:${amounts(k)}`).join(' ')
}
function nanoToSem(nano) {
return nano / 1e9
}
function shortHash(hash) {
return hash.substr(2, 4)
}
// ---------------------------------------------------------------
// libs
function $objValues(obj) {
return Object.keys(obj).map((k) => obj[k])
}
function $mapObj(keyValFn, objIn) {
const objOut = {}
for (const key in objIn) {
const val = objIn[key]
objOut[key] = keyValFn({ key, val })
}
return objOut
}
function $objSumValues(obj) {
const initialVal = 0
return $objValues(obj)
.reduce((v1, v2) => v1 + v2, initialVal)
}
function $updateKey(key, valFn, obj) {
return {
...obj,
[key]: valFn(obj[key])
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment