Skip to content

Instantly share code, notes, and snippets.

@dcolley
Created May 10, 2023 15:11
Show Gist options
  • Save dcolley/d9efb5fee52f9143430794f3fe40dc19 to your computer and use it in GitHub Desktop.
Save dcolley/d9efb5fee52f9143430794f3fe40dc19 to your computer and use it in GitHub Desktop.
/*
Checks if an address has votes, and removes them if needed
Edit the NODE_WS_URL as needed
*/
import { Keyring, ApiPromise, WsProvider } from '@polkadot/api'
import readline from 'readline';
const NODE_WS_URL = 'wss://rpc.ibp.network/kusama'
// const NODE_WS_URL = 'wss://rpc.ibp.network/polkadot'
// protect the mnemonic from being displayed on the terminal
// qudos: https://gist.github.com/colgatto/22a2933889eda0a51645374b5bd70e3b
function ask(query, hidden = false) {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
if(hidden){
let t = true;
rl._writeToOutput = (a) => {
if(t){
rl.output.write(a);
t = false;
}
};
}
return new Promise(resolve => rl.question(query, ans => {
if(hidden) rl.output.write('\n\r');
rl.close();
resolve(ans);
})
);
}
;(async () => {
const provider = new WsProvider(NODE_WS_URL)
const api = await ApiPromise.create({ provider })
const chainInfo = JSON.parse(api.registry.getChainProperties().toString())
// console.debug('chainInfo', chainInfo) //.toJSON())
const denom = Math.pow(10, chainInfo.tokenDecimals[0]) || -1000000000000
// console.debug('denom', denom)
// const account = 'HyLisujX7Cr6D7xzb6qadFdedLt8hmArB6ZVGJ6xsCUHqmx'
const account = await ask('Enter your account address, or Ctrl+C to exit:\n')
console.log('Checking account', account, 'for votes\n')
const classLocks = await api.query.convictionVoting.classLocksFor(account)
console.debug('classLocks', classLocks.toJSON().sort((a, b) => a[0] - b[0]))
const trackIds = [
0, // Root
1, // Whitelisted Caller
2, 3, 4, 5, 6, 7, 8, 9,
10, // Staking Admin
11, // Treasurer
12, // Lease Admin
13, // Fellowship Admin
14, // General Admin
15, // AuctionAdmin
16, 17, 18, 19,
20, // Referendum Canceller
21, // Referendum Killer
22,
21, 23, 24, 25, 26, 27, 28, 29,
30, // Small Tipper
31, // Big Tipper
32, // Small Spender
33, // Medium Spender
34, // Big Spender
35,
// 36
]
const txs = []
for (let trackId = 0; trackId < 36; trackId++) {
// console.debug('trackId', trackId)
const result = await api.query.convictionVoting.votingFor(account, trackId) //, async (result) => {
//console.debug('votingFor', trackId, result.toJSON())
const trackVote = result.toJSON()
if (trackVote.delegating) {
console.debug('delegatingFor', trackId, trackVote.delegating.target, trackVote.delegating.balance/denom, trackVote.delegating.conviction)
}
if (trackVote.casting) {
for(let i = 0; i < trackVote.casting.votes.length; i++) {
const [refId, vote] = trackVote.casting.votes[i]
console.debug('votingFor', trackId, refId, vote)
txs.push(api.tx.convictionVoting.removeVote(trackId, refId))
}
}
if (!trackVote.delegating && !trackVote.casting) {
console.debug('unknown state', trackVote.toJSON())
}
}
if( txs.length > 0) {
console.log(`\nThere are ${txs.length} vote(s) to remove, please confirm.\n`)
const answer = await ask('Press [y] to continue, or Ctrl+C to exit:\n')
if (!['y', 'Y'].includes(answer)) {
console.log('Exiting')
process.exit()
} else {
const mnemonic = await ask('Enter your mnemonic, or Ctrl+C to exit (mnemonic will not be shown on screen):\n', true)
// const mnemonic = 'mushroom cage bulb kiwi kiwi kiwi kiwi kiwi kiwi kiwi kiwi kiwi kiwi'
const keyring = new Keyring({ type: 'sr25519' });
const signer = keyring.addFromMnemonic(mnemonic)
console.log('Signing with address hash:', signer.address.toString())
// console.log(signer.toJson())
const [events=[], status] = await api.tx.utility.batch(txs).signAndSend(signer)
if (status.isInBlock) {
console.debug(`batch included in ${status.asInBlock}`)
} else {
console.debug('status', status)
}
process.exit()
}
} else {
console.log('No votes to remove')
process.exit()
}
})()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment