-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: #60, Check if preimage exists on chain before creating a proposal #61
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,8 @@ | ||
const { getConfiguration } = require("opstooling-js-style/src/eslint/configuration"); | ||
|
||
module.exports = getConfiguration({ typescript: { rootDir: __dirname } }); | ||
const conf = getConfiguration({ typescript: { rootDir: __dirname } }); | ||
|
||
conf.overrides[0].rules["@typescript-eslint/no-misused-promises"] = "off"; | ||
conf.overrides[0].rules["no-async-promise-executor"] = "off"; | ||
|
||
module.exports = conf; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,11 +2,13 @@ import "@polkadot/api-augment"; | |
import "@polkadot/types-augment"; | ||
import { ApiPromise } from "@polkadot/api"; | ||
import { KeyringPair } from "@polkadot/keyring/types"; | ||
import { ISubmittableResult } from "@polkadot/types/types"; | ||
import { blake2AsHex } from "@polkadot/util-crypto"; | ||
import assert from "assert"; | ||
import { Probot } from "probot"; | ||
|
||
import { getChainConfig, getTipUrl } from "./chain-config"; | ||
import { State, TipRequest, TipResult } from "./types"; | ||
import { ContributorAccount, State, TipRequest, TipResult } from "./types"; | ||
import { formatReason, tipSizeToOpenGovTrack } from "./util"; | ||
|
||
export async function tipOpenGov(opts: { | ||
|
@@ -29,40 +31,73 @@ export async function tipOpenGov(opts: { | |
if ("error" in track) { | ||
return { success: false, errorMessage: track.error }; | ||
} | ||
const contributorAddress = contributor.account.address; | ||
|
||
const proposalTx = api.tx.utility.batch([ | ||
api.tx.system.remark(formatReason(tipRequest)), | ||
api.tx.treasury.spend(track.value.toString(), contributor.account.address), | ||
api.tx.treasury.spend(track.value.toString(), contributorAddress), | ||
]); | ||
const encodedProposal = proposalTx.method.toHex(); | ||
const proposalHash = blake2AsHex(encodedProposal); | ||
const encodedLength = Math.ceil((encodedProposal.length - 2) / 2); | ||
|
||
const preimage_unsub = await api.tx.preimage | ||
.notePreimage(encodedProposal) | ||
.signAndSend(botTipAccount, { nonce: -1 }, (result) => { | ||
if (result.status.isInBlock) { | ||
bot.log(`Preimage Upload included at blockHash ${result.status.asInBlock.toString()}`); | ||
} else if (result.status.isFinalized) { | ||
bot.log(`Preimage Upload finalized at blockHash ${result.status.asFinalized.toString()}`); | ||
preimage_unsub(); | ||
} | ||
}); | ||
return await new Promise(async (resolve, reject) => { | ||
// create a preimage from opengov with the encodedProposal above | ||
const preimageUnsubscribe = await api.tx.preimage | ||
.notePreimage(encodedProposal) | ||
.signAndSend(botTipAccount, { nonce: -1 }, async (result) => { | ||
await signAndSendCallback(bot, contributor.account, "preimage", preimageUnsubscribe, result) | ||
.then(async () => { | ||
const readPreimage = await api.query.preimage.statusFor(proposalHash); | ||
|
||
const referenda_unsub = await api.tx.referenda | ||
.submit( | ||
// TODO: There should be a way to set those types properly. | ||
{ Origins: track.track } as any, // eslint-disable-line | ||
{ Lookup: { hash: proposalHash, length: proposalTx.length - 1 } }, | ||
{ after: 10 } as any, // eslint-disable-line | ||
) | ||
.signAndSend(botTipAccount, { nonce: -1 }, (result) => { | ||
if (result.status.isInBlock) { | ||
bot.log(`Tip referendum included at blockHash ${result.status.asInBlock.toString()}`); | ||
} else if (result.status.isFinalized) { | ||
bot.log(`Tip referendum finalized at blockHash ${result.status.asFinalized.toString()}`); | ||
referenda_unsub(); | ||
} | ||
}); | ||
if (readPreimage.isEmpty) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Asking for understanding: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
this is what happens with creating a preimage
|
||
reject(new Error(`Preimage for ${proposalHash} was not found, check if the bot has enough funds.`)); | ||
} | ||
|
||
return { success: true, tipUrl: getTipUrl(contributor.account.network) }; | ||
const proposalUnsubscribe = await api.tx.referenda | ||
.submit( | ||
// TODO: There should be a way to set those types properly. | ||
{ Origins: track.track } as never, | ||
{ Lookup: { hash: proposalHash, len: encodedLength } }, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Here's some logs
when I create it, in polkadotjs it shows 85 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just added 5 chars to a remark, and got 90 as final size in polkadotjs so it means to me
all 3 will give same correct size of preimage I just used last as this is most commonly used There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay yea then just use what works. The TS code is fucked either way. |
||
{ after: 10 } as never, | ||
) | ||
.signAndSend(botTipAccount, { nonce: -1 }, async (refResult) => { | ||
await signAndSendCallback(bot, contributor.account, "referendum", proposalUnsubscribe, refResult) | ||
.then(resolve) | ||
.catch(reject); | ||
}); | ||
}) | ||
.catch(reject); | ||
}); | ||
}); | ||
} | ||
|
||
async function signAndSendCallback( | ||
bot: Probot, | ||
contributor: ContributorAccount, | ||
type: "preimage" | "referendum", | ||
unsubscribe: () => void, | ||
result: ISubmittableResult, | ||
): Promise<TipResult> { | ||
return await new Promise((resolve, reject) => { | ||
if (result.status.isInBlock) { | ||
bot.log(`${type} for ${contributor.address} included at blockHash ${result.status.asInBlock.toString()}`); | ||
} else if (result.status.isFinalized) { | ||
bot.log(`Tip for ${contributor.address} ${type} finalized at blockHash ${result.status.asFinalized.toString()}`); | ||
unsubscribe(); | ||
resolve({ success: true, tipUrl: getTipUrl(contributor.network) }); | ||
} else if ( | ||
result.status.isDropped || | ||
result.status.isInvalid || | ||
result.status.isUsurped || | ||
result.status.isRetracted || | ||
result.status.isBroadcast | ||
) { | ||
const msg = `Tip for ${contributor.address} ${type} status is 👎: ${result.status.type}`; | ||
bot.log(msg, result.status); | ||
reject({ success: false, errorMessage: msg }); | ||
} else { | ||
bot.log(`Tip for ${contributor.address} ${type} status: ${result.status.type}`, result.status); | ||
} | ||
}); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this calculation? It needs to be the SCALE encoded length.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
before it was
proposalTx.length - 1
, but this I took from https://github.com/polkadot-js/apps/blob/2d295e33f9d37d6582d97b9e93df81d16e1950e2/packages/page-preimages/src/Preimages/Add/Partial.tsx#L44@ggwpez could you please explain what is SCALE encoded?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It first does
toHex
and then uses(x - 2) / 2
to get the number of bytes in the hex string… wtfMaybe there is no easier way to encode it or something. Ideal would be an
encode
orencodedLength
function.Otherwise just add a test; i dont want to block over this if it works.
SCALE is the encoding that Substrate/Polkadot uses for mostly everything. Especially stuff like transactions and their arguments (so also preimages).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll investigate and we will add tests for sure