Last active
January 14, 2024 01:24
-
-
Save anpigon/3b99074a9d078bb90487d38d657ec5ed to your computer and use it in GitHub Desktop.
obsidian 노트앱의 Tamplater 플러그인용 스팀 수익 자동 조회 스크립트
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
var __defProp = Object.defineProperty; | |
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | |
var __getOwnPropNames = Object.getOwnPropertyNames; | |
var __hasOwnProp = Object.prototype.hasOwnProperty; | |
var __export = (target, all) => { | |
for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); | |
}; | |
var __copyProps = (to, from, except, desc) => { | |
if ((from && typeof from === 'object') || typeof from === 'function') { | |
for (let key of __getOwnPropNames(from)) | |
if (!__hasOwnProp.call(to, key) && key !== except) | |
__defProp(to, key, { | |
get: () => from[key], | |
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable, | |
}); | |
} | |
return to; | |
}; | |
// src/main.ts | |
module.exports = main; | |
var ID = /* @__PURE__ */ ((ID2) => { | |
ID2['Follow'] = 'follow'; | |
ID2['Notify'] = 'notify'; | |
return ID2; | |
})(ID || {}); | |
var MaxAcceptedPayout = /* @__PURE__ */ ((MaxAcceptedPayout2) => { | |
MaxAcceptedPayout2['The1000000000Sbd'] = '1000000.000 SBD'; | |
return MaxAcceptedPayout2; | |
})(MaxAcceptedPayout || {}); | |
var TentacledOp = /* @__PURE__ */ ((TentacledOp2) => { | |
TentacledOp2['CommentOptions'] = 'comment_options'; | |
TentacledOp2['CustomJSON'] = 'custom_json'; | |
TentacledOp2['DelegateVestingShares'] = 'delegate_vesting_shares'; | |
return TentacledOp2; | |
})(TentacledOp || {}); | |
var ConfidentialSbdSupply = /* @__PURE__ */ ((ConfidentialSbdSupply2) => { | |
ConfidentialSbdSupply2['The0000Sbd'] = '0.000 SBD'; | |
return ConfidentialSbdSupply2; | |
})(ConfidentialSbdSupply || {}); | |
var StickyOp = /* @__PURE__ */ ((StickyOp2) => { | |
StickyOp2['AuthorReward'] = 'author_reward'; | |
StickyOp2['ClaimRewardBalance'] = 'claim_reward_balance'; | |
StickyOp2['CommentBenefactorReward'] = 'comment_benefactor_reward'; | |
StickyOp2['CurationReward'] = 'curation_reward'; | |
StickyOp2['Transfer'] = 'transfer'; | |
StickyOp2['TransferToVesting'] = 'transfer_to_vesting'; | |
return StickyOp2; | |
})(StickyOp || {}); | |
var HEADER = { 'content-type': 'application/json' }; | |
function api(method, params) { | |
return fetch('https://api.steemit.com/', { | |
headers: HEADER, | |
method: 'POST', | |
body: JSON.stringify({ | |
id: 0, | |
jsonrpc: '2.0', | |
method, | |
params, | |
}), | |
}).then((res) => res.json()); | |
} | |
function call(params) { | |
return api('call', params); | |
} | |
function databaseApi(method, params) { | |
return call(['database_api', method, params]).then((res) => res.result); | |
} | |
function getVestingDelegations(username, start_account = '', limit = 1e3) { | |
return databaseApi('get_vesting_delegations', [username, start_account, limit]); | |
} | |
function getTransfers(username) { | |
return databaseApi('get_state', [`/@${username}/transfers`]); | |
} | |
function getAccountPosts(username, limit = 20) { | |
return api('bridge.get_account_posts', { | |
sort: 'posts', | |
account: username, | |
observer: username, | |
limit, | |
}).then((res) => res.result); | |
} | |
async function getCurrentSteemMarketPrice(timestamp) { | |
const urls = [ | |
`https://api.upbit.com/v1/candles/days?market=KRW-STEEM&count=1&to=${timestamp}T23:59:59`, | |
`https://api.upbit.com/v1/candles/days?market=KRW-SBD&count=1&to=${timestamp}T23:59:59`, | |
]; | |
const [steemResponse, sdbResponse] = await Promise.all(urls.map((url) => fetch(url).then((res) => res.json()))); | |
return { | |
steem: steemResponse[0].trade_price, | |
sbd: sdbResponse[0].trade_price, | |
}; | |
} | |
function calculateSteemPower(vest, total_vesting_fund_steem, total_vesting_shares) { | |
return parseFloat( | |
((parseFloat(vest) * parseFloat(total_vesting_fund_steem)) / parseFloat(total_vesting_shares)).toFixed(8), | |
); | |
} | |
async function main(username, timestamp) { | |
let results = ''; | |
const KRW = await getCurrentSteemMarketPrice(timestamp); | |
const state = await getTransfers(username); | |
const { total_vesting_fund_steem, total_vesting_shares } = state.props; | |
const { base, quote } = state.feed_price; | |
const steemPrice = parseFloat(base) / parseFloat(quote); | |
const transferHistory = state.accounts[username].transfer_history | |
.filter((h) => h.length > 1 && 'timestamp' in h[1] && h[1].timestamp.startsWith(timestamp)) | |
.map((h) => h[1].op); | |
const vestingDelegations = await getVestingDelegations(username); | |
const delegations = vestingDelegations.reduce((acc, { delegatee, vesting_shares }) => { | |
const steemPower = calculateSteemPower(vesting_shares, total_vesting_fund_steem, total_vesting_shares); | |
return { ...acc, [delegatee]: steemPower }; | |
}, {}); | |
const accountPosts = await getAccountPosts(username); | |
const activeVotes = accountPosts | |
.filter((post) => post.created.startsWith(timestamp) && post.active_votes.length > 0) | |
.map(({ payout, net_rshares, active_votes }) => { | |
return active_votes | |
.map(({ rshares, voter }) => ({ | |
voter, | |
value: (parseFloat(rshares) / net_rshares) * payout, | |
})) | |
.filter((vote) => vote.value); | |
}) | |
.flatMap((votes) => votes); | |
const transferAccounts = transferHistory | |
.filter((h) => h[0] === 'transfer') | |
.map((h) => h[1]) | |
.reduce((acc, cur) => { | |
const [quantity, currency] = cur.amount.split(' '); | |
const result = acc[cur.from] || { steem: 0, sbd: 0 }; | |
if (currency === 'STEEM') { | |
result['steem'] += parseFloat(quantity); | |
} | |
if (currency === 'SBD') { | |
result['sbd'] += parseFloat(quantity); | |
} | |
acc[cur.from] = result; | |
return acc; | |
}, {}); | |
const delegationsSteem = Object.entries(delegations).map(([delegatee, steemPower]) => { | |
var _a, _b, _c, _d; | |
const transferSteem = | |
(_b = (_a = transferAccounts[delegatee == 'upvu' ? 'upvu.bank' : delegatee]) == null ? void 0 : _a.steem) != null | |
? _b | |
: 0; | |
const upvoteValue = | |
(_d = (_c = activeVotes.find((vote) => vote.voter === delegatee)) == null ? void 0 : _c.value) != null ? _d : 0; | |
const upvoteSteem = upvoteValue / steemPrice; | |
const apr = ((transferSteem + upvoteSteem) / steemPower) * 365 * 100; | |
return { delegatee, steemPower, transferSteem, upvoteSteem, apr }; | |
}); | |
const history = []; | |
for (const [type, payload] of transferHistory) { | |
if ( | |
type === 'transfer' && | |
payload.to === username && | |
payload.from !== username && | |
!payload.from.endsWith('.dunamu') | |
) { | |
const isSteem = payload.amount.endsWith(' STEEM'); | |
const isSbd = payload.amount.endsWith(' SBD'); | |
const value = parseFloat(payload.amount); | |
const steemValue = isSteem ? value : 0; | |
const sbdValue = isSbd ? value : 0; | |
history.push({ | |
type, | |
steem: steemValue, | |
sbd: sbdValue, | |
sp: 0, | |
link: `@${payload.from}`, | |
}); | |
} else if (type === 'curation_reward' && payload.curator === username) { | |
const steemPower = calculateSteemPower(payload.reward, total_vesting_fund_steem, total_vesting_shares); | |
history.push({ | |
type, | |
steem: 0, | |
sbd: 0, | |
sp: steemPower, | |
link: `@${payload.comment_author}/${payload.comment_permlink}`, | |
}); | |
} else if (type === 'comment_benefactor_reward' && payload.benefactor === username) { | |
const link = `@${payload.author}/${payload.permlink}`; | |
const vestSteem = calculateSteemPower(payload.vesting_payout, total_vesting_fund_steem, total_vesting_shares); | |
history.push({ | |
type: 'author_reward', | |
steem: parseFloat(payload.steem_payout), | |
sbd: parseFloat(payload.sbd_payout), | |
sp: vestSteem, | |
link, | |
}); | |
} else if (type === 'author_reward') { | |
const link = `@${payload.author}/${payload.permlink}`; | |
const vestSteem = calculateSteemPower(payload.vesting_payout, total_vesting_fund_steem, total_vesting_shares); | |
if ( | |
parseFloat(payload.steem_payout) + parseFloat(payload.sbd_payout) + parseFloat(payload.vesting_payout) === | |
0 | |
) { | |
continue; | |
} | |
history.push({ | |
type, | |
steem: parseFloat(payload.steem_payout), | |
sbd: parseFloat(payload.sbd_payout), | |
sp: vestSteem, | |
link, | |
}); | |
} | |
} | |
const totalTransferSteem = history.filter(({ type }) => type === 'transfer').reduce((acc, cur) => acc + cur.steem, 0); | |
const totalTransferSbd = history.filter(({ type }) => type === 'transfer').reduce((acc, cur) => acc + cur.sbd, 0); | |
const totalTransferKRW = totalTransferSteem * KRW.steem + totalTransferSbd * KRW.sbd; | |
const totalCuratorRewardSp = history | |
.filter(({ type }) => type === 'curation_reward') | |
.reduce((acc, cur) => acc + cur.sp, 0); | |
const totalCuratorRewardKRW = totalCuratorRewardSp * KRW.steem; | |
const totalAuthorRewardSp = history | |
.filter(({ type }) => type === 'author_reward') | |
.reduce((acc, cur) => acc + cur.sp, 0); | |
const totalAuthorRewardSteem = history | |
.filter(({ type }) => type === 'author_reward') | |
.reduce((acc, cur) => acc + cur.steem, 0); | |
const totalAuthorRewardSbd = history | |
.filter(({ type }) => type === 'author_reward') | |
.reduce((acc, cur) => acc + cur.sbd, 0); | |
const totalAuthorRewardKRW = | |
(totalAuthorRewardSp + totalAuthorRewardSteem) * KRW.steem + totalAuthorRewardSbd * KRW.sbd; | |
results += ` | |
### Market(\uC885\uAC00) | |
| Steem Price | SBD Price | | |
| --- | --- | | |
`; | |
results += `| ${KRW.steem} KRW | ${KRW.sbd.toLocaleString()} KRW | | |
`; | |
results += ` | |
### Summary | |
`; | |
results += `| | STEEM | SBD | SP | KRW | | |
| --- | --- | --- | --- |--- | | |
`; | |
results += `| \uC784\uB300 \uC218\uC775 | ${totalTransferSteem.toFixed(3)} | ${totalTransferSbd.toFixed( | |
3, | |
)} | 0 | ${totalTransferKRW.toFixed(0).toLocaleString()} | | |
`; | |
results += `| \uC800\uC790 \uC218\uC775 | ${totalAuthorRewardSteem.toFixed(3)} | ${totalAuthorRewardSbd.toFixed( | |
3, | |
)} | ${totalAuthorRewardSp.toFixed(3)} | ${Math.floor(totalAuthorRewardKRW).toLocaleString()} | | |
`; | |
results += `| \uD050\uB808\uC774\uC158 \uC218\uC775 | 0 | 0 | ${totalCuratorRewardSp.toFixed(3)} | ${Math.floor( | |
totalCuratorRewardKRW, | |
).toLocaleString()} | | |
`; | |
results += `| Total | ${(totalTransferSteem + totalAuthorRewardSteem).toFixed(3)} | ${( | |
totalTransferSbd + totalAuthorRewardSbd | |
).toFixed(3)} | ${(totalAuthorRewardSp + totalCuratorRewardSp).toFixed(3)} | ${Math.floor( | |
totalTransferKRW + totalAuthorRewardKRW + totalCuratorRewardKRW, | |
).toLocaleString()} | | |
`; | |
results += ` | |
### Delegations | |
| DELEGATEE | VESTING | TRANSFER | UPVOTE | APR | | |
| --- | --- | --- | --- | --- | | |
`; | |
delegationsSteem | |
.sort((a, b) => b.apr - a.apr) | |
.forEach(({ delegatee, steemPower, transferSteem, upvoteSteem, apr }) => { | |
results += `| ${delegatee} | ${Math.floor(steemPower)} SP | ${transferSteem.toFixed( | |
3, | |
)} STEEM | ${upvoteSteem.toFixed(3)} STEEM | ${apr.toFixed(2)}% | | |
`; | |
}); | |
results += ` | |
### History | |
| TYPE | STEEM | SBD | SP | URL | | |
| --- | --- | --- | --- | --- | | |
`; | |
history | |
.sort((a, b) => a.type.localeCompare(b.type)) | |
.forEach(({ type, steem, sbd, sp, link }) => { | |
results += `| ${type} | ${steem.toFixed(3)} | ${sbd.toFixed(3)} | ${sp.toFixed( | |
3, | |
)} | [${link}](https://steemit.com/${link}) | | |
`; | |
}); | |
return results; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment