Skip to content

Instantly share code, notes, and snippets.

@witoldsz
Last active October 11, 2018 20:47
Show Gist options
  • Save witoldsz/be9060579b6ec80730f08a85d2c2a145 to your computer and use it in GitHub Desktop.
Save witoldsz/be9060579b6ec80730f08a85d2c2a145 to your computer and use it in GitHub Desktop.
jedna8 created by witoldsz - https://repl.it/@witoldsz/jedna8
const DELEGATE_ADDR = '0x6f673a46f3529a8e0933145dde78d91004a5d944'
const TXS_URL = `https://semux.online/v2.1.0/account/transactions?address=${DELEGATE_ADDR}&from=${0}&to=99999`
const BURNED_SEM_OWNER = shortHash('0x0d2a67855fae0a04509198d7591f9c09450053cf')
const BURNED_SEM_PAID_DATE = new Date('2018-10-10T00:00:00Z')
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) => (
isStakeIn(tx) ? stakeInAction(state, tx)
: isStakeOut(tx) ? stakeOutAction(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 stakeInAction(state, tx) {
const owner = shortHash(tx.from)
const amount = nanoToSem(tx.value)
const oldStakes = state.stakes
const newStakes = {
...oldStakes,
[owner]: (oldStakes[owner] || 0) + amount
}
const oldGains = state.gains
const newGains = {
...oldGains,
[owner]: oldGains[owner] || 0,
}
console.log(`${showDate(tx)},STAKE_IN,${owner},${amount},${showValues(newStakes)}`)
return { ...state, stakes: newStakes, gains: newGains }
}
function stakeOutAction(state, tx) {
const recipient = shortHash(tx.to)
const amount = nanoToSem(tx.value)
const oldStakes = state.stakes
const newStakes = {
...oldStakes,
[recipient]: oldStakes[recipient] - amount,
}
const oldGains = state.gains
const newGains = {
...oldGains,
[recipient]: oldGains[recipient] - amount,
}
console.log(`${showDate(tx)},STAKE_OUT,${recipient},${amount},${showValues(newStakes)}`)
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 newStakes = $mapObj(
({ key: owner, val: stake }) => stake + gainOf(owner, stake, totalStake, tx),
oldStakes
)
const newGains = $mapObj(
({ key: owner, val: ownerGain }) => ownerGain + gainOf(owner, oldStakes[owner], totalStake, tx),
state.gains
)
console.log(`${showDate(tx)},SELF_VOTE,${Math.round(amount)},${showValues(newGains)}`)
return { ...state, stakes: newStakes, gains: newGains }
}
function isStakeIn(tx) {
return tx.type === 'VOTE'
&& tx.from !== DELEGATE_ADDR
&& tx.to === DELEGATE_ADDR
}
function isStakeOut(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(owner, stake, totalStake, tx) {
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)
}
function showValues(stakes) {
return JSON.stringify(roundValues(stakes))
}
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 nanoToSem(nano) {
return nano / 1e9
}
function shortHash(hash) {
return hash.substr(2, 6)
}
// ---------------------------------------------------------------
// 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)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment