forked from Joystream/community-repo
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathproposals.ts
More file actions
159 lines (148 loc) · 5.62 KB
/
proposals.ts
File metadata and controls
159 lines (148 loc) · 5.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import { WsProvider, ApiPromise } from "@polkadot/api";
import { types } from "@joystream/types";
import {
Active,
Approved,
ExecutionFailed,
Finalized,
Proposal,
ProposalDetails,
ProposalId,
} from "@joystream/types/proposals";
import { StorageKey, Vec } from "@polkadot/types";
import { Membership } from "@joystream/types/members";
// import { Stake, Staked, StakeId } from "@joystream/types/stake";
import { AnyJson } from "@polkadot/types/types";
interface ProposalOverview {
id: number;
type: string;
title: string;
createdBy: [number, string];
stakeId: number;
stake: number;
created: number;
status: string;
finalizedAt?: number;
result?: string;
feePaid?: number;
executionStatus?: string;
executeAt?: number;
voteResult?: AnyJson;
execution?: AnyJson;
}
async function main() {
// Initialise the provider to connect to the local node
const provider = new WsProvider("ws://127.0.0.1:9944");
//If you want to play around on our staging network, go ahead and connect to this staging network instead.
//const provider = new WsProvider('wss://testnet-rpc-2-singapore.joystream.org');
// Create the API and wait until ready
const api = await ApiPromise.create({ provider, types });
const allProposals: ProposalOverview[] = [];
// get all proposalIds
// sort them by id
const proposalKeys = await api.query.proposalsEngine.proposals.keys();
const proposalIds = proposalKeys.map(
({ args: [proposalId] }) => proposalId
) as Vec<ProposalId>;
proposalIds.sort((a, b) => +a - +b);
console.log("number of proposals", proposalIds.length);
// get all stakeIds associated with proposalIds
const stakeIdOfProposalId =
(await api.query.proposalsEngine.stakesProposals.keys()) as StorageKey[];
const stakeIdsOfProposalIds = stakeIdOfProposalId.map(
({ args: [stakeId] }) => stakeId
) as Vec<StakeId>;
stakeIdsOfProposalIds.sort((a, b) => +a - +b);
console.log("number of stakeIdsOfProposalIds:", stakeIdsOfProposalIds.length);
for (let id of proposalIds) {
const proposal = (await api.query.proposalsEngine.proposals(
id
)) as Proposal;
const proposerHandle = (
(await api.query.members.membershipById(
proposal.proposerId
)) as Membership
).handle.toString();
const proposalStatus = proposal.status.value;
const proposalDetails =
(await api.query.proposalsCodex.proposalDetailsByProposalId(
id
)) as ProposalDetails;
let stakeId = stakeIdsOfProposalIds[proposalIds.indexOf(id)];
let stake = 0;
if (
((await api.query.proposalsEngine.stakesProposals(
stakeId
)) as ProposalId) === id
) {
const blockHash = await api.rpc.chain.getBlockHash(proposal.createdAt);
const proposalStake = (await api.query.stake.stakes.at(
blockHash,
stakeId
)) as Stake;
if (proposalStake.staking_status.isOfType('Staked')) {
stake += Number((proposalStake.staking_status.asType('Staked') as Staked).staked_amount);
}
}
const proposalData: ProposalOverview = {
id: +id,
type: proposalDetails.type.toString(),
title: Buffer.from(proposal.title.toString().substr(2), 'hex').toString(),
createdBy: [+proposal.proposerId, proposerHandle],
stakeId: +stakeId,
stake,
created: +proposal.createdAt,
status: proposal.status.value.toString(),
};
// these proposals will have an annoyngly large 'execution'
if (
proposalDetails.type != "Text" &&
proposalDetails.type != "RuntimeUpgrade"
) {
proposalData.execution = proposalDetails.value.toHuman();
}
// check if the proposal is "Active"
if (proposalStatus instanceof Active) {
proposalData.status = proposalStatus.toString();
} else {
// There really isn't any other options here...
if (proposalStatus instanceof Finalized) {
proposalData.status = proposalStatus.proposalStatus.type;
proposalData.finalizedAt = +proposalStatus.finalizedAt;
proposalData.voteResult = proposal.votingResults.toHuman();
const proposalResult = proposalStatus.proposalStatus.value;
// check if the proposal is "Approved"
if (proposalResult instanceof Approved) {
proposalData.feePaid = 0;
const gracePeriod = +proposal.parameters.gracePeriod;
proposalData.executeAt = +proposalStatus.finalizedAt + gracePeriod;
proposalData.executionStatus = proposalResult.type;
// "Executed" and "PendingExecution" works differently than "ExecutionFailed"
// the latter will have some information on what went wrong
if (proposalResult.isOfType("Executed")) {
} else if (proposalResult.isOfType("PendingExecution")) {
} else if (proposalResult.value instanceof ExecutionFailed) {
proposalData.executionStatus =
proposalResult.type + `:` + proposalResult.value.error.toString();
}
} else {
// If not finalized, but not approved, it must be one of...
if (proposalStatus.proposalStatus.isOfType("Canceled")) {
proposalData.feePaid = 10000;
} else if (proposalStatus.proposalStatus.isOfType("Slashed")) {
proposalData.feePaid = stake;
} else if (proposalStatus.proposalStatus.isOfType("Vetoed")) {
proposalData.feePaid = 0;
// .. "Expired" or "Rejected", which are treated as the same.
} else {
proposalData.feePaid = 5000;
}
}
}
}
allProposals.push(proposalData);
}
console.log("allProposals", JSON.stringify(allProposals, null, 4));
await api.disconnect();
}
main();