mirror of https://github.com/certusone/santa.git
initial commit
This commit is contained in:
parent
2187ab6df2
commit
1d0ba63c44
|
@ -59,3 +59,86 @@ typings/
|
|||
|
||||
# next.js build output
|
||||
.next
|
||||
|
||||
node_modules/
|
||||
.node_modules/
|
||||
built/*
|
||||
tests/cases/rwc/*
|
||||
tests/cases/test262/*
|
||||
tests/cases/perf/*
|
||||
!tests/cases/webharness/compilerToString.js
|
||||
test-args.txt
|
||||
~*.docx
|
||||
\#*\#
|
||||
.\#*
|
||||
tests/baselines/local/*
|
||||
tests/baselines/local.old/*
|
||||
tests/services/baselines/local/*
|
||||
tests/baselines/prototyping/local/*
|
||||
tests/baselines/rwc/*
|
||||
tests/baselines/test262/*
|
||||
tests/baselines/reference/projectOutput/*
|
||||
tests/baselines/local/projectOutput/*
|
||||
tests/baselines/reference/testresults.tap
|
||||
tests/services/baselines/prototyping/local/*
|
||||
tests/services/browser/typescriptServices.js
|
||||
src/harness/*.js
|
||||
src/compiler/diagnosticInformationMap.generated.ts
|
||||
src/compiler/diagnosticMessages.generated.json
|
||||
src/parser/diagnosticInformationMap.generated.ts
|
||||
src/parser/diagnosticMessages.generated.json
|
||||
rwc-report.html
|
||||
*.swp
|
||||
build.json
|
||||
*.actual
|
||||
tests/webTestServer.js
|
||||
tests/webTestServer.js.map
|
||||
tests/webhost/*.d.ts
|
||||
tests/webhost/webtsc.js
|
||||
tests/cases/**/*.js
|
||||
tests/cases/**/*.js.map
|
||||
*.config
|
||||
scripts/debug.bat
|
||||
scripts/run.bat
|
||||
scripts/word2md.js
|
||||
scripts/buildProtocol.js
|
||||
scripts/ior.js
|
||||
scripts/authors.js
|
||||
scripts/configurePrerelease.js
|
||||
scripts/open-user-pr.js
|
||||
scripts/open-cherry-pick-pr.js
|
||||
scripts/processDiagnosticMessages.d.ts
|
||||
scripts/processDiagnosticMessages.js
|
||||
scripts/produceLKG.js
|
||||
scripts/importDefinitelyTypedTests/importDefinitelyTypedTests.js
|
||||
scripts/generateLocalizedDiagnosticMessages.js
|
||||
scripts/*.js.map
|
||||
scripts/typings/
|
||||
coverage/
|
||||
internal/
|
||||
**/.DS_Store
|
||||
.settings
|
||||
**/.vs
|
||||
**/.vscode
|
||||
!**/.vscode/tasks.json
|
||||
!tests/cases/projects/projectOption/**/node_modules
|
||||
!tests/cases/projects/NodeModulesSearch/**/*
|
||||
!tests/baselines/reference/project/nodeModules*/**/*
|
||||
.idea
|
||||
yarn.lock
|
||||
yarn-error.log
|
||||
.parallelperf.*
|
||||
tests/cases/user/*/package-lock.json
|
||||
tests/cases/user/*/node_modules/
|
||||
tests/cases/user/*/**/*.js
|
||||
tests/cases/user/*/**/*.js.map
|
||||
tests/cases/user/*/**/*.d.ts
|
||||
!tests/cases/user/zone.js/
|
||||
!tests/cases/user/bignumber.js/
|
||||
!tests/cases/user/discord.js/
|
||||
tests/baselines/reference/dt
|
||||
.failed-tests
|
||||
TEST-results.xml
|
||||
package-lock.json
|
||||
|
||||
unsignedTx.json
|
|
@ -0,0 +1 @@
|
|||
export {};
|
|
@ -0,0 +1,151 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const core = require("@terra-money/core");
|
||||
const rest_1 = require("./utils/rest");
|
||||
const big_js_1 = require("big.js");
|
||||
const fs = require("fs");
|
||||
const rest = new rest_1.default("http://127.0.0.1:1317");
|
||||
const outputFile = "./unsignedTx.json";
|
||||
const foundationAddress = "terra1dp0taj85ruc299rkdvzp4z5pfg6z6swaed74e6";
|
||||
const goliathValAddress = "terravaloper163phlen6dn7sp9khhjar2gqqx6kga0ly8d7h9g";
|
||||
const marineValAddress = "terravaloper1d3hatwcsvkktgwp3elglw9glca0h42yg6xy4lp";
|
||||
const ghostValAddress = "terravaloper1rgu3qmm6rllfxlrfk94pgxa0jm37902dynqehm";
|
||||
const wraithValAddress = "terravaloper1eutun6vh83lmyq0wmyf9vgghvurze2xanl9sq6";
|
||||
async function loadFoundationRewards() {
|
||||
const promises = [];
|
||||
promises.push(rest.loadDelegatorRewards(foundationAddress));
|
||||
promises.push(rest.loadValidatorRewards(goliathValAddress));
|
||||
promises.push(rest.loadValidatorRewards(marineValAddress));
|
||||
promises.push(rest.loadValidatorRewards(ghostValAddress));
|
||||
promises.push(rest.loadValidatorRewards(wraithValAddress));
|
||||
const rewardMap = {};
|
||||
await Promise.all(promises)
|
||||
.then(res => {
|
||||
for (let i in res) {
|
||||
const rewards = res[i];
|
||||
if (rewards && rewards.length > 0) {
|
||||
for (let j in rewards) {
|
||||
const denom = rewards[j].denom;
|
||||
const amount = rewards[j].amount.split('.')[0];
|
||||
if (rewardMap[denom]) {
|
||||
rewardMap[denom] = big_js_1.default(rewardMap[denom]).plus(amount).toString();
|
||||
}
|
||||
else {
|
||||
rewardMap[denom] = amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
const totalRewards = [];
|
||||
for (let denom in rewardMap) {
|
||||
totalRewards.push({
|
||||
denom: denom,
|
||||
amount: rewardMap[denom]
|
||||
});
|
||||
}
|
||||
return totalRewards;
|
||||
}
|
||||
const validatorBonusRate = 0.2;
|
||||
function computeValidatorsRewardRatio(rewardRatioMap, validators) {
|
||||
let totalBondedToken = big_js_1.default(0);
|
||||
for (let i in validators) {
|
||||
totalBondedToken = totalBondedToken.plus(validators[i].tokens);
|
||||
}
|
||||
for (let i in validators) {
|
||||
const validator = validators[i];
|
||||
const address = core.convertValAddressToAccAddress(validator.operator_address);
|
||||
rewardRatioMap[address] = big_js_1.default(validator.tokens).div(totalBondedToken).mul(validatorBonusRate).toString();
|
||||
}
|
||||
return;
|
||||
}
|
||||
async function computeDelegatorRewardRatio(rewardRatioMap, validators) {
|
||||
let totalBondedToken = big_js_1.default(0);
|
||||
for (let i in validators) {
|
||||
totalBondedToken = totalBondedToken.plus(validators[i].tokens);
|
||||
}
|
||||
for (let i in validators) {
|
||||
const validator = validators[i];
|
||||
const delegations = await rest.loadDelegations(validator.operator_address);
|
||||
if (!delegations)
|
||||
continue;
|
||||
for (let j in delegations) {
|
||||
const delegation = delegations[j];
|
||||
const tokens = big_js_1.default(validator.tokens).mul(delegations[j].shares).div(validator.delegator_shares);
|
||||
const ratio = big_js_1.default(tokens).div(totalBondedToken).mul(1 - validatorBonusRate).toString();
|
||||
if (rewardRatioMap[delegation.delegator_address]) {
|
||||
rewardRatioMap[delegation.delegator_address]
|
||||
= big_js_1.default(rewardRatioMap[delegation.delegator_address])
|
||||
.plus(ratio).toString();
|
||||
}
|
||||
else {
|
||||
rewardRatioMap[delegation.delegator_address] = ratio;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
async function main() {
|
||||
const foundationRewards = await loadFoundationRewards();
|
||||
console.debug("Foundation Rewards:", foundationRewards);
|
||||
const validators = await rest.loadValidators();
|
||||
if (!validators) {
|
||||
console.error("no validator found");
|
||||
return process.exit(-1);
|
||||
}
|
||||
const rewardRatioMap = {};
|
||||
computeValidatorsRewardRatio(rewardRatioMap, validators);
|
||||
console.info("Validator Bonus Rewards: ", rewardRatioMap);
|
||||
await computeDelegatorRewardRatio(rewardRatioMap, validators);
|
||||
console.info("Total Rewards: ", rewardRatioMap);
|
||||
// Rotate reward ratio and build msg input
|
||||
let totalRatio = big_js_1.default(0);
|
||||
const outputs = [];
|
||||
for (let addr in rewardRatioMap) {
|
||||
const ratio = rewardRatioMap[addr];
|
||||
totalRatio = totalRatio.plus(ratio);
|
||||
const coins = [];
|
||||
for (let i in foundationRewards) {
|
||||
coins.push({
|
||||
denom: foundationRewards[i].denom,
|
||||
amount: big_js_1.default(foundationRewards[i].amount).mul(ratio).toFixed(0)
|
||||
});
|
||||
}
|
||||
outputs.push({
|
||||
address: addr,
|
||||
coins: coins
|
||||
});
|
||||
}
|
||||
if (totalRatio.gt(1)) {
|
||||
console.error(`Total Reward Ratio(${totalRatio}) is bigger than 1`);
|
||||
return process.exit(-1);
|
||||
}
|
||||
const inputs = [];
|
||||
const coins = [];
|
||||
for (let i in foundationRewards) {
|
||||
coins.push({
|
||||
denom: foundationRewards[i].denom,
|
||||
amount: big_js_1.default(foundationRewards[i].amount).toFixed(0)
|
||||
});
|
||||
}
|
||||
inputs.push({
|
||||
address: foundationAddress,
|
||||
coins: coins
|
||||
});
|
||||
const multiSendMsg = core.buildMultiSend(inputs, outputs);
|
||||
const unSingedTx = core.buildStdTx([multiSendMsg], { gas: "1000000", amount: [{
|
||||
denom: "ukrw",
|
||||
amount: "1000000"
|
||||
}] }, "reward distribution");
|
||||
fs.writeFile(outputFile, JSON.stringify(unSingedTx, null, 4), function (err) {
|
||||
if (err) {
|
||||
console.error("Writing Failed", err);
|
||||
}
|
||||
else {
|
||||
console.info("Writing Succeed", `Please check ${outputFile}`);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
main();
|
||||
//# sourceMappingURL=index.js.map
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,36 @@
|
|||
declare class RestInterface {
|
||||
lcdAddress: string;
|
||||
constructor(lcdAddress: string);
|
||||
loadValidators(): Promise<void | Array<Validator>>;
|
||||
loadValidatorRewards(valAddress: string): Promise<void | Array<Coin>>;
|
||||
loadDelegations(valAddress: string): Promise<void | Array<Delegation>>;
|
||||
loadDelegatorRewards(delAddress: string): Promise<void | Array<Coin>>;
|
||||
}
|
||||
export interface Validator {
|
||||
operator_address: string;
|
||||
consensus_pubkey: string;
|
||||
jailed: boolean;
|
||||
status: number;
|
||||
tokens: string;
|
||||
delegator_shares: string;
|
||||
description: [Object];
|
||||
unbonding_height: string;
|
||||
unbonding_time: string;
|
||||
commission: [Object];
|
||||
min_self_delegation: string;
|
||||
}
|
||||
export interface Delegation {
|
||||
delegator_address: string;
|
||||
validator_address: string;
|
||||
shares: string;
|
||||
}
|
||||
export interface Coin {
|
||||
denom: string;
|
||||
amount: string;
|
||||
}
|
||||
export interface ValidatorRewardsInfo {
|
||||
operator_address: string;
|
||||
self_bond_rewards: [Coin];
|
||||
val_commission: [Coin];
|
||||
}
|
||||
export default RestInterface;
|
|
@ -0,0 +1,51 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const axios_1 = require("axios");
|
||||
class RestInterface {
|
||||
constructor(lcdAddress) {
|
||||
this.lcdAddress = lcdAddress;
|
||||
}
|
||||
async loadValidators() {
|
||||
const queryValidatorsURL = `${this.lcdAddress}/staking/validators`;
|
||||
try {
|
||||
const res = await axios_1.default.get(queryValidatorsURL);
|
||||
return res.data ? res.data : [];
|
||||
}
|
||||
catch (error) {
|
||||
console.error("[LoadValidators]", error);
|
||||
}
|
||||
}
|
||||
async loadValidatorRewards(valAddress) {
|
||||
const queryValidatorRewardsInfoURL = `${this.lcdAddress}/distribution/validators/${valAddress}`;
|
||||
try {
|
||||
const res = await axios_1.default.get(queryValidatorRewardsInfoURL);
|
||||
// foundation validators have 100% commission, so ignore self_bond_rewards
|
||||
return res.data ? res.data.val_commission : [];
|
||||
}
|
||||
catch (error) {
|
||||
console.error("[LoadValidatorRewardsInfoURL]", error);
|
||||
}
|
||||
}
|
||||
async loadDelegations(valAddress) {
|
||||
const queryDelegatorsURL = `${this.lcdAddress}/staking/validators/${valAddress}/delegations`;
|
||||
try {
|
||||
const res = await axios_1.default.get(queryDelegatorsURL);
|
||||
return res.data ? res.data : [];
|
||||
}
|
||||
catch (error) {
|
||||
console.error("[LoadDelegations]", error);
|
||||
}
|
||||
}
|
||||
async loadDelegatorRewards(delAddress) {
|
||||
const queryDelegatorRewardsURL = `${this.lcdAddress}/distribution/delegators/${delAddress}/rewards`;
|
||||
try {
|
||||
const res = await axios_1.default.get(queryDelegatorRewardsURL);
|
||||
return res.data ? res.data : [];
|
||||
}
|
||||
catch (error) {
|
||||
console.error("[LoadDelegatorRewards]", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.default = RestInterface;
|
||||
//# sourceMappingURL=rest.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"rest.js","sourceRoot":"src/","sources":["utils/rest.ts"],"names":[],"mappings":";;AAAA,iCAA4C;AAE5C,MAAM,aAAa;IAGjB,YAAY,UAAkB;QAC5B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;IAC9B,CAAC;IAED,KAAK,CAAC,cAAc;QAClB,MAAM,kBAAkB,GAAG,GAAG,IAAI,CAAC,UAAU,qBAAqB,CAAA;QAClE,IAAI;YACF,MAAM,GAAG,GAAG,MAAM,eAAK,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAA;YAC/C,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAA;SAChC;QAAC,OAAO,KAAK,EAAE;YACd,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;SAC1C;IACH,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,UAAkB;QAC3C,MAAM,4BAA4B,GAAG,GAAG,IAAI,CAAC,UAAU,4BAA4B,UAAU,EAAE,CAAA;QAC/F,IAAI;YACF,MAAM,GAAG,GAAG,MAAM,eAAK,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAA;YACzD,0EAA0E;YAC1E,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,CAAA;SAC/C;QAAC,OAAO,KAAK,EAAE;YACd,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAC;SACvD;IACH,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,UAAkB;QACtC,MAAM,kBAAkB,GAAG,GAAG,IAAI,CAAC,UAAU,uBAAuB,UAAU,cAAc,CAAA;QAC5F,IAAI;YACF,MAAM,GAAG,GAAG,MAAM,eAAK,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAA;YAC/C,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAA;SAChC;QAAC,OAAO,KAAK,EAAE;YACd,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAC;SAC3C;IACH,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,UAAkB;QAC3C,MAAM,wBAAwB,GAAG,GAAG,IAAI,CAAC,UAAU,4BAA4B,UAAU,UAAU,CAAA;QACnG,IAAI;YACF,MAAM,GAAG,GAAG,MAAM,eAAK,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAA;YACrD,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAA;SAChC;QAAC,OAAO,KAAK,EAAE;YACd,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC;SAChD;IACH,CAAC;CACF;AAiCD,kBAAe,aAAa,CAAA"}
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "reward-distributor",
|
||||
"version": "1.0.0",
|
||||
"description": "terra foundation reward distributor to validators & delegators",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"build": "tsc --declaration",
|
||||
"start": "node ./dist/index.js"
|
||||
},
|
||||
"author": "YunSuk Yeo <sw.yunsuk@gmail.com>",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@terra-money/core": "^1.0.2",
|
||||
"@types/axios": "^0.14.0",
|
||||
"@types/big.js": "^4.0.5",
|
||||
"@types/loglevel": "^1.5.4",
|
||||
"axios": "^0.19.0",
|
||||
"big.js": "^5.2.2",
|
||||
"loglevel": "^1.6.3"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,176 @@
|
|||
import * as core from "@terra-money/core"
|
||||
import {default as RestInterface, Coin, Validator, ValidatorRewardsInfo} from "./utils/rest"
|
||||
import bn from "big.js"
|
||||
import * as fs from "fs"
|
||||
|
||||
|
||||
const rest = new RestInterface("http://127.0.0.1:1317")
|
||||
const outputFile = "./unsignedTx.json"
|
||||
|
||||
const foundationAddress = "terra1dp0taj85ruc299rkdvzp4z5pfg6z6swaed74e6"
|
||||
const goliathValAddress = "terravaloper163phlen6dn7sp9khhjar2gqqx6kga0ly8d7h9g"
|
||||
const marineValAddress = "terravaloper1d3hatwcsvkktgwp3elglw9glca0h42yg6xy4lp"
|
||||
const ghostValAddress = "terravaloper1rgu3qmm6rllfxlrfk94pgxa0jm37902dynqehm"
|
||||
const wraithValAddress = "terravaloper1eutun6vh83lmyq0wmyf9vgghvurze2xanl9sq6"
|
||||
|
||||
async function loadFoundationRewards(): Promise<Array<Coin>> {
|
||||
const promises: Array<Promise<void | Array<Coin>>> = []
|
||||
promises.push(rest.loadDelegatorRewards(foundationAddress))
|
||||
promises.push(rest.loadValidatorRewards(goliathValAddress))
|
||||
promises.push(rest.loadValidatorRewards(marineValAddress))
|
||||
promises.push(rest.loadValidatorRewards(ghostValAddress))
|
||||
promises.push(rest.loadValidatorRewards(wraithValAddress))
|
||||
|
||||
const rewardMap = {}
|
||||
await Promise.all(promises)
|
||||
.then(res => {
|
||||
for (let i in res) {
|
||||
const rewards = res[i]
|
||||
|
||||
if (rewards && rewards.length > 0) {
|
||||
for (let j in rewards) {
|
||||
const denom = rewards[j].denom
|
||||
const amount = rewards[j].amount.split('.')[0]
|
||||
if (rewardMap[denom]) {
|
||||
rewardMap[denom] = bn(rewardMap[denom]).plus(amount).toString()
|
||||
} else {
|
||||
rewardMap[denom] = amount
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const totalRewards: Array<Coin> = []
|
||||
for (let denom in rewardMap) {
|
||||
totalRewards.push({
|
||||
denom: denom,
|
||||
amount: rewardMap[denom]
|
||||
})
|
||||
}
|
||||
|
||||
return totalRewards
|
||||
}
|
||||
|
||||
const validatorBonusRate = 0.2
|
||||
function computeValidatorsRewardRatio(rewardRatioMap: object, validators: Array<Validator>) {
|
||||
let totalBondedToken = bn(0)
|
||||
for (let i in validators) {
|
||||
totalBondedToken = totalBondedToken.plus(validators[i].tokens)
|
||||
}
|
||||
|
||||
for (let i in validators) {
|
||||
const validator = validators[i]
|
||||
const address = core.convertValAddressToAccAddress(validator.operator_address)
|
||||
rewardRatioMap[address] = bn(validator.tokens).div(totalBondedToken).mul(validatorBonusRate).toString()
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
async function computeDelegatorRewardRatio(rewardRatioMap: object, validators: Array<Validator>): Promise<void> {
|
||||
let totalBondedToken = bn(0)
|
||||
for (let i in validators) {
|
||||
totalBondedToken = totalBondedToken.plus(validators[i].tokens)
|
||||
}
|
||||
|
||||
for (let i in validators) {
|
||||
const validator = validators[i]
|
||||
const delegations = await rest.loadDelegations(validator.operator_address)
|
||||
|
||||
if (!delegations) continue
|
||||
|
||||
for (let j in delegations) {
|
||||
const delegation = delegations[j]
|
||||
const tokens = bn(validator.tokens).mul(delegations[j].shares).div(validator.delegator_shares)
|
||||
const ratio = bn(tokens).div(totalBondedToken).mul(1 - validatorBonusRate).toString()
|
||||
|
||||
if (rewardRatioMap[delegation.delegator_address]) {
|
||||
rewardRatioMap[delegation.delegator_address]
|
||||
= bn(rewardRatioMap[delegation.delegator_address])
|
||||
.plus(ratio).toString()
|
||||
} else {
|
||||
rewardRatioMap[delegation.delegator_address] = ratio
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
async function main() {
|
||||
|
||||
const foundationRewards = await loadFoundationRewards()
|
||||
console.debug("Foundation Rewards:", foundationRewards)
|
||||
|
||||
const validators = await rest.loadValidators()
|
||||
if (!validators) {
|
||||
console.error("no validator found")
|
||||
return process.exit(-1)
|
||||
}
|
||||
|
||||
const rewardRatioMap = {}
|
||||
computeValidatorsRewardRatio(rewardRatioMap, validators)
|
||||
console.info("Validator Bonus Rewards: ", rewardRatioMap)
|
||||
|
||||
await computeDelegatorRewardRatio(rewardRatioMap, validators)
|
||||
console.info("Total Rewards: ", rewardRatioMap)
|
||||
|
||||
// Rotate reward ratio and build msg input
|
||||
let totalRatio = bn(0)
|
||||
const outputs: Array<core.InOut> = []
|
||||
for (let addr in rewardRatioMap) {
|
||||
const ratio = rewardRatioMap[addr]
|
||||
totalRatio = totalRatio.plus(ratio)
|
||||
|
||||
const coins: Array<core.Coin> = []
|
||||
for (let i in foundationRewards) {
|
||||
coins.push({
|
||||
denom: foundationRewards[i].denom,
|
||||
amount: bn(foundationRewards[i].amount).mul(ratio).toFixed(0)
|
||||
})
|
||||
}
|
||||
|
||||
outputs.push({
|
||||
address: addr,
|
||||
coins: coins
|
||||
})
|
||||
}
|
||||
|
||||
if (totalRatio.gt(1)) {
|
||||
console.error(`Total Reward Ratio(${totalRatio}) is bigger than 1`)
|
||||
return process.exit(-1)
|
||||
}
|
||||
|
||||
const inputs: Array<core.InOut> = []
|
||||
const coins: Array<core.Coin> = []
|
||||
for (let i in foundationRewards) {
|
||||
coins.push({
|
||||
denom: foundationRewards[i].denom,
|
||||
amount: bn(foundationRewards[i].amount).toFixed(0)
|
||||
})
|
||||
}
|
||||
|
||||
inputs.push({
|
||||
address: foundationAddress,
|
||||
coins: coins
|
||||
})
|
||||
|
||||
const multiSendMsg = core.buildMultiSend(inputs, outputs)
|
||||
const unSingedTx = core.buildStdTx([multiSendMsg], {gas: "1000000", amount: [{
|
||||
denom: "ukrw",
|
||||
amount: "1000000"
|
||||
}]}, "reward distribution")
|
||||
|
||||
fs.writeFile(outputFile, JSON.stringify(unSingedTx, null, 4), function(err) {
|
||||
if (err) {
|
||||
console.error("Writing Failed", err);
|
||||
} else {
|
||||
console.info("Writing Succeed", `Please check ${outputFile}`)
|
||||
}
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
main()
|
|
@ -0,0 +1,83 @@
|
|||
import axios, { AxiosResponse } from "axios"
|
||||
|
||||
class RestInterface {
|
||||
lcdAddress: string
|
||||
|
||||
constructor(lcdAddress: string) {
|
||||
this.lcdAddress = lcdAddress
|
||||
}
|
||||
|
||||
async loadValidators(): Promise<void | Array<Validator>> {
|
||||
const queryValidatorsURL = `${this.lcdAddress}/staking/validators`
|
||||
try {
|
||||
const res = await axios.get(queryValidatorsURL)
|
||||
return res.data ? res.data : []
|
||||
} catch (error) {
|
||||
console.error("[LoadValidators]", error);
|
||||
}
|
||||
}
|
||||
|
||||
async loadValidatorRewards(valAddress: string): Promise<void | Array<Coin>> {
|
||||
const queryValidatorRewardsInfoURL = `${this.lcdAddress}/distribution/validators/${valAddress}`
|
||||
try {
|
||||
const res = await axios.get(queryValidatorRewardsInfoURL)
|
||||
// foundation validators have 100% commission, so ignore self_bond_rewards
|
||||
return res.data ? res.data.val_commission : []
|
||||
} catch (error) {
|
||||
console.error("[LoadValidatorRewardsInfoURL]", error);
|
||||
}
|
||||
}
|
||||
|
||||
async loadDelegations(valAddress: string): Promise<void | Array<Delegation>> {
|
||||
const queryDelegatorsURL = `${this.lcdAddress}/staking/validators/${valAddress}/delegations`
|
||||
try {
|
||||
const res = await axios.get(queryDelegatorsURL)
|
||||
return res.data ? res.data : []
|
||||
} catch (error) {
|
||||
console.error("[LoadDelegations]", error);
|
||||
}
|
||||
}
|
||||
|
||||
async loadDelegatorRewards(delAddress: string): Promise<void | Array<Coin>> {
|
||||
const queryDelegatorRewardsURL = `${this.lcdAddress}/distribution/delegators/${delAddress}/rewards`
|
||||
try {
|
||||
const res = await axios.get(queryDelegatorRewardsURL)
|
||||
return res.data ? res.data : []
|
||||
} catch (error) {
|
||||
console.error("[LoadDelegatorRewards]", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface Validator {
|
||||
operator_address: string
|
||||
consensus_pubkey: string
|
||||
jailed: boolean
|
||||
status: number
|
||||
tokens: string
|
||||
delegator_shares: string
|
||||
description: [Object]
|
||||
unbonding_height: string
|
||||
unbonding_time: string
|
||||
commission: [Object]
|
||||
min_self_delegation: string
|
||||
}
|
||||
|
||||
export interface Delegation {
|
||||
delegator_address: string
|
||||
validator_address: string
|
||||
shares: string
|
||||
}
|
||||
|
||||
export interface Coin {
|
||||
denom: string
|
||||
amount: string
|
||||
}
|
||||
|
||||
export interface ValidatorRewardsInfo {
|
||||
operator_address:string
|
||||
self_bond_rewards:[Coin]
|
||||
val_commission:[Coin]
|
||||
}
|
||||
|
||||
export default RestInterface
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2018",
|
||||
"module": "commonjs",
|
||||
"strict": false,
|
||||
"allowJs": false,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"moduleResolution": "node",
|
||||
"skipLibCheck": true,
|
||||
"strictNullChecks": true,
|
||||
"sourceMap": true,
|
||||
"baseUrl": "src",
|
||||
"sourceRoot": "src",
|
||||
"outDir": "dist",
|
||||
"typeRoots": [
|
||||
"./src/typings",
|
||||
"./node_modules/@types"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist"
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue