js-conflux-sdk
Version:
JavaScript Conflux Software Development Kit
473 lines (450 loc) • 12.8 kB
JavaScript
const RPCMethodFactory = require('./index');
const format = require('../util/format');
const LATEST_COMMITTED = 'latest_committed';
const LATEST_VOTED = 'latest_voted';
format.posBlockNumber = format.bigUIntHex
.$or(LATEST_COMMITTED)
.$or(LATEST_VOTED);
/**
* @typedef {Object} PivotDecision
* @property {number} height
* @property {string} blockHash
*/
format.decision = format({
height: format.uInt,
});
/**
* PoS status
* @typedef {Object} PoSStatus
* @property {number} latestCommitted
* @property {number} epoch
* @property {number} latestVoted
* @property {number} latestTxNumber
* @property {PivotDecision} pivotDecision
*/
format.posStatus = format({
latestCommitted: format.uInt,
epoch: format.uInt,
pivotDecision: format.decision,
latestTxNumber: format.uInt,
latestVoted: format.uInt.$or(null),
});
/**
* @typedef {Object} VotePowerState
* @property {number} endBlockNumber
* @property {number} power
*/
format.posVotePowerState = format({
endBlockNumber: format.uInt,
power: format.uInt,
});
/**
* @typedef {Object} PoSAccountStatus
* @property {number} availableVotes
* @property {number} forfeited
* @property {VotePowerState[]} inQueue
* @property {VotePowerState[]} outQueue
* @property {number} locked
* @property {number} unlocked
* @property {number|null} forceRetired
*/
/**
* @typedef {Object} PoSAccount
* @property {number} blockNumber
* @property {PoSAccountStatus} status
*/
format.posAccount = format({
blockNumber: format.uInt,
status: {
availableVotes: format.uInt,
forfeited: format.uInt,
forceRetired: format.uInt.$or(null),
inQueue: [format.posVotePowerState],
locked: format.uInt,
outQueue: [format.posVotePowerState],
unlocked: format.uInt,
},
});
format.txPayload = format({
targetTerm: format.uInt,
}).$or({
votingPower: format.uInt,
}).$or({
height: format.uInt,
});
/**
* @typedef {Object} PoSTransaction
* @property {string} hash
* @property {string} blockHash
* @property {string} from
* @property {string} status
* @property {string} type
* @property {number} number
* @property {number|null} timestamp
* @property {number|null} blockNumber
* @property {*} payload
*/
format.posTransaction = format({
number: format.uInt,
timestamp: format.uInt.$or(null),
blockNumber: format.uInt.$or(null),
payload: format.txPayload.$or(null),
}).$or(null);
/**
* @typedef {Object} Signature
* @property {number} votes
* @property {string} account
*/
/**
* @typedef {Object} PoSBlock
* @property {number} epoch
* @property {number} height
* @property {PivotDecision} pivotDecision
* @property {number} round
* @property {number} timestamp
* @property {number} lastTxNumber
* @property {Signature} signatures
*/
format.posBlock = format({
epoch: format.uInt,
height: format.uInt,
pivotDecision: format.decision.$or(null),
round: format.uInt,
timestamp: format.uInt,
lastTxNumber: format.uInt,
signatures: [format({ votes: format.uInt })],
}).$or(null);
/**
* @typedef {Object} CommitteeNode
* @property {number} votingPower
* @property {string} address
*/
format.committeeNode = format({
votingPower: format.uInt,
});
/**
* @typedef {Object} Election
* @property {boolean} isFinalized
* @property {number} startBlockNumber
* @property {CommitteeNode[]} topElectingNodes
*/
format.election = format({
startBlockNumber: format.uInt,
topElectingNodes: [format.committeeNode],
});
/**
* @typedef {Object} CurrentCommittee
* @property {number} epochNumber
* @property {number} quorumVotingPower
* @property {number} totalVotingPower
* @property {CommitteeNode[]} nodes
*/
/**
* @typedef {Object} PoSCommittee
* @property {CurrentCommittee} currentCommittee
* @property {Election[]} elections
*/
format.committee = format({
currentCommittee: {
epochNumber: format.uInt,
quorumVotingPower: format.uInt,
totalVotingPower: format.uInt,
nodes: [format.committeeNode],
},
elections: [format.election],
});
/**
* @typedef {Object} PoSReward
* @property {number} reward
* @property {string} posAddress
* @property {string} powAddress
*/
/**
* @typedef {Object} PoSEpochRewards
* @property {string} powEpochHash
* @property {PoSReward[]} accountRewards
*/
format.rewardsByEpoch = format({
accountRewards: format([format({
reward: format.bigUInt,
})]).$or(null),
}).$or(null);
format.epochState = format.any;
format.ledgerInfoWithSignatures = format.any;
/**
* Class contains pos RPC methods
* For the detail meaning of fields, please refer to the PoS RPC document:
* @class
*/
class PoS extends RPCMethodFactory {
/**
* Create PoS instance
* @param {import('../Conflux').Conflux} conflux The Conflux object
* @return {PoS} The PoS instance
*/
constructor(conflux) {
super(conflux, PoS.methods());
this.conflux = conflux;
}
static methods() {
return [
/**
* @instance
* @async
* @name getStatus
* @return {Promise<PoSStatus>} PoS status object
* @example
* await conflux.pos.getStatus();
* // {
* // epoch: 138,
* // latestCommitted: 8235,
* // latestTxNumber: '0xa5e2',
* // latestVoted: 8238,
* // pivotDecision: {
* // blockHash: '0x97625d04ece6fe322ae38010ac877447927b4d5963af7eaea7db9befb615e510',
* // height: 394020
* // }
* // }
*/
{
method: 'pos_getStatus',
responseFormatter: format.posStatus,
},
/**
* @instance
* @async
* @name getAccount
* @param {Hash} account Account address
* @param {number|hex} [blockNumber] Optional block number
* @return {Promise<PoSAccount>}
* @example
* await conflux.pos.getAccount('0x0f0ccf5ee5276b102316acb3943a2750085f85ac7b94bdbf9d8901f03a7d7cc3');
* {
* address: '0x0f0ccf5ee5276b102316acb3943a2750085f85ac7b94bdbf9d8901f03a7d7cc3',
* blockNumber: 8240,
* status: {
* availableVotes: 1525,
* forceRetired: null,
* forfeited: 0,
* inQueue: [],
* locked: 1525,
* outQueue: [],
* unlocked: 1
* }
* }
*/
{
method: 'pos_getAccount',
requestFormatters: [
format.hex64,
format.posBlockNumber.$or(undefined),
],
responseFormatter: format.posAccount,
},
{
method: 'pos_getAccountByPowAddress',
requestFormatters: [
format.address,
format.posBlockNumber.$or(undefined),
],
responseFormatter: format.posAccount,
},
/**
* @instance
* @async
* @name getBlockByHash
* @param {string} hash The hash of PoS block
* @return {Promise<PoSBlock>}
* @example
* await conflux.pos.getBlockByHash('0x97625d04ece6fe322ae38010ac877447927b4d5963af7eaea7db9befb615e510');
*/
{
method: 'pos_getBlockByHash',
requestFormatters: [
format.hex64,
],
responseFormatter: format.posBlock,
},
/**
* @instance
* @async
* @name getBlockByNumber
* @param {number|hex} blockNumber The number of PoS block
* @return {Promise<PoSBlock>}
* @example
* await conflux.pos.getBlockByNumber(8235);
* {
* epoch: 138,
* hash: '0x1daf5443b7556cc39c3d4fe5e208fa77c3f5c053ea4bd637f5e43dfa7f0a95cb',
* height: 8235,
* miner: '0x0f0ccf5ee5276b102316acb3943a2750085f85ac7b94bdbf9d8901f03a7d7cc3',
* lastTxNumber: 42467,
* parentHash: '0x308699b307c81906ab97cbf213532c196f2d718f4641266aa444209349d9e31c',
* pivotDecision: {
* blockHash: '0x97625d04ece6fe322ae38010ac877447927b4d5963af7eaea7db9befb615e510',
* height: 394020
* },
* round: 15,
* signatures: [
* {
* account: '0x00f7c03318f8c4a7c6ae432e124b4a0474e973139a87f9ea6ae3efba66af7d8a',
* votes: 3
* }
* ],
* timestamp: 1638340165169041
* }
*/
{
method: 'pos_getBlockByNumber',
requestFormatters: [
format.posBlockNumber,
],
responseFormatter: format.posBlock,
},
/**
* @instance
* @async
* @name getCommittee
* @param {number|hex} [blockNumber] Optional block number
* @return {Promise<PoSCommittee>}
* @example
* await conflux.pos.getCommittee();
* {
* currentCommittee: {
* epochNumber: 138,
* nodes: [
* {
* address: "0xf92d8504fad118ddb5cf475180f5bcffaa967a9f9fa9c3c899ff9ad0de99694a",
* votingPower: 3
* }
* ],
* quorumVotingPower: 199,
* totalVotingPower: 297
* },
* elections: [
* {
* isFinalized: false,
* startBlockNumber: 8280,
* topElectingNodes: [
* {
* address: "0x0f0ccf5ee5276b102316acb3943a2750085f85ac7b94bdbf9d8901f03a7d7cc3",
* votingPower: 3
* }
* ]
* },
* {
* isFinalized: false,
* startBlockNumber: 8340,
* topElectingNodes: []
* }
* ]
* }
*/
{
method: 'pos_getCommittee',
requestFormatters: [
format.posBlockNumber.$or(undefined),
],
responseFormatter: format.committee,
},
/**
* @instance
* @async
* @name getTransactionByNumber
* @param {number|string} txNumber The number of transaction
* @return {Promise<PoSTransaction>}
* @example
* await conflux.pos.getTransactionByNumber(8235);
* {
* blockHash: '0xe684e88981b7ffe14741a2274e7b65b89ae2e133ebdd783d71ddeeacb4e957d6',
* blockNumber: 8243,
* from: '0x0000000000000000000000000000000000000000000000000000000000000000',
* hash: '0xaa92222b6a20342285ed56de2b77a05a6c1a9a3e4750e4952af8f908f7316b5d',
* number: 42480,
* payload: null,
* status: 'Executed',
* timestamp: 1638340649662468,
* type: 'BlockMetadata'
* }
*/
{
method: 'pos_getTransactionByNumber',
requestFormatters: [
format.bigUIntHex,
],
responseFormatter: format.posTransaction,
},
/**
* @instance
* @async
* @method getRewardsByEpoch
* @name getRewardsByEpoch
* @param {number|string} epoch A PoS epoch number
* @return {Promise<PoSEpochRewards>}
* @example
* await conflux.pos.getRewardsByEpoch(138);
* {
* accountRewards: [
* {
* posAddress: '0x83ca56dd7b9d1222fff48565ed0261f42a17099061d905f9e743f89574dbd8e0',
* powAddress: 'NET8888:TYPE.USER:AAKFSH1RUYS4P040J5M7DJRJBGMX9ZV7HAJTFN2DKP',
* reward: 605265415757735647n
* },
* ... 122 more items
* ],
* powEpochHash: '0xd634c0a71c6197a6fad9f80439b31b4c7191b3ee42335b1548dad1160f7f628c'
* }
*/
{
method: 'pos_getRewardsByEpoch',
requestFormatters: [
format.bigUIntHex,
],
responseFormatter: format.rewardsByEpoch,
},
{
method: 'pos_getConsensusBlocks',
requestFormatters: [
],
responseFormatter: format([format.posBlock]),
},
{
method: 'pos_getEpochState',
requestFormatters: [
format.bigUIntHex,
],
responseFormatter: format.epochState,
},
{
method: 'pos_getLedgerInfoByEpoch',
requestFormatters: [
format.bigUIntHex,
],
responseFormatter: format.ledgerInfoWithSignatures.$or(undefined),
},
{
method: 'pos_getLedgerInfoByBlockNumber',
requestFormatters: [
format.posBlockNumber,
],
responseFormatter: format.ledgerInfoWithSignatures.$or(undefined),
},
{
method: 'pos_getLedgerInfoByEpochAndRound',
requestFormatters: [
format.bigUIntHex,
format.bigUIntHex,
],
responseFormatter: format.ledgerInfoWithSignatures.$or(undefined),
},
{
method: 'pos_getLedgerInfosByEpoch',
requestFormatters: [
format.bigUIntHex,
],
responseFormatter: format([format.ledgerInfoWithSignatures]),
},
];
}
}
module.exports = PoS;