Created
July 11, 2023 14:35
-
-
Save jsdw/0a27b8c98293ebd082d629d0b3e6d2e2 to your computer and use it in GitHub Desktop.
Signing a transaction with polkadot JS browser extension
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as dapp from "@polkadot/extension-dapp"; | |
import { Keyring } from "@polkadot/ui-keyring"; | |
import { | |
mnemonicGenerate, | |
cryptoWaitReady, | |
signatureVerify, | |
decodeAddress, | |
} from "@polkadot/util-crypto"; | |
import { stringToU8a, u8aToHex, stringToHex, hexToU8a } from "@polkadot/util"; | |
import keyring from "@polkadot/ui-keyring"; | |
import { ApiPromise, WsProvider } from "@polkadot/api"; | |
//// This is the JSON format we need to pass to a signer: | |
// export interface SignerPayloadJSON { | |
// /** The ss-58 encoded address */ | |
// address: string; | |
// /** The checkpoint hash of the block, in hex */ | |
// blockHash: string; | |
// /** The checkpoint block number, in hex */ | |
// blockNumber: string; | |
// /** The era for this transaction, in hex */ | |
// era: string; | |
// /** The genesis hash of the chain, in hex */ | |
// genesisHash: string; | |
// /** The encoded method (with arguments) in hex */ | |
// method: string; | |
// /** The nonce for this transaction, in hex */ | |
// nonce: string; | |
// /** The current spec version for the runtime */ | |
// specVersion: string; | |
// /** The tip for this transaction, in hex */ | |
// tip: string; | |
// /** The current transaction version for the runtime */ | |
// transactionVersion: string; | |
// /** The applicable signed extensions for this runtime */ | |
// signedExtensions: string[]; | |
// /** The version of the extrinsic we are dealing with */ | |
// version: number; | |
// } | |
await main(); | |
async function main() { | |
await cryptoWaitReady(); | |
await dapp.web3Enable("my cool dapp"); | |
// In "real life" hopefully we can use: | |
// | |
// const allInjected = await dapp.web3Enable("my cool dapp"); | |
// // get an account by some specific address; we can also search in other ways. | |
// const alice = await dapp.web3FromAddress("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"); | |
// // use account to sign the payload provided. | |
// alice.signer.signPayload(payload) | |
// | |
// But Talisman seems to get stuck trying to work with local nodes (see | |
// https://github.com/TalismanSociety/talisman/issues/923), and PJS, for | |
// me at least, doesn't load properly (inc latest version), but the below | |
// line seems to prod it into working properly instead. | |
var pjs = await injectedWeb3["polkadot-js"].enable("my cool app"); | |
// The payload format was obtained from starting a `polkadot --dev` node, | |
// and a dev version of the `polkadot-js/extension` (by going to about:debugging#addons | |
// in firefox and then loading `packages/extension/build/manifest.json` after doing an | |
// `yarn && npm run build` to actually build the thing). I tweaked the dev version to | |
// console.log the payload in the `signPayload` function so we could see what PJS UI | |
// handed it (I expect I could have added the log in PJS UI instead but hey ho). | |
// | |
// To get the payload values, I'd suggest plucking them out of Subxt at first: | |
// - specVersion and transactionVersion and genesisHash are available via `OfflineClient`. | |
// - `era` and `blockHash` and `blockNumber` I think are the mortality things; `blockHash` | |
// can be `genesisHash` or whatever the checkpoint block is, `blockNumber` must match, | |
// and `era` I'm not certain about offhand; can stick to immortal transactions though as below. | |
// - `method` is the hex encoded call data | |
// - `nonce` is the hex encoded account nonce | |
// - `signedExtensions` is the list of extensions which can be obtained from Metadata. | |
// - `tip` is a tip to give (I guess there's no way to tip in a different asset atm?). | |
// - `version` is 4; the tx protocol version. | |
// | |
// Would be cool if we could get PJS to automatically decode a signer payload into this, | |
// though that would then require PJS to be present, and doing it ourselves we can basically | |
// avoid that. | |
let { signature } = await pjs.signer.signPayload({ | |
"specVersion": "0x000024d6", | |
"transactionVersion": "0x00000018", | |
"address": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", | |
"blockHash": "0xd7aad6185db012b7ffbce710b55234d6c9589170566b925ee50cfa3d7f1e6f8f", | |
"blockNumber": "0x00000000", | |
"era": "0x0000", | |
"genesisHash": "0xd7aad6185db012b7ffbce710b55234d6c9589170566b925ee50cfa3d7f1e6f8f", | |
"method": "0x0503001cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c0b00c465f14670", | |
"nonce": "0x00000000", | |
"signedExtensions": [ | |
"CheckNonZeroSender", | |
"CheckSpecVersion", | |
"CheckTxVersion", | |
"CheckGenesis", | |
"CheckMortality", | |
"CheckNonce", | |
"CheckWeight", | |
"ChargeTransactionPayment", | |
"PrevalidateAttests" | |
], | |
"tip": "0x00000000000000000000000000000000", | |
"version": 4 | |
}) | |
// Signature seems to be a 65 byte thing, so probably already a MultiSignature ie the format we want. | |
console.log("signature:", signature) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment