Skip to content

Commit

Permalink
Browser extension signing example (#1067)
Browse files Browse the repository at this point in the history
* routing and signing example

* cliipy fix

* submitting extrinsics

* change order of lines

* Skip call variants if there aren't any (#980)

Co-authored-by: Niklas Adolfsson <[email protected]>

* Tidy up some metadata accessing (#978)

* Reduce some repetition when obtaining metadata pallets/runtime_traits

* make them pub

* fix docs and clippy

* Bump tokio from 1.28.1 to 1.28.2 (#984)

Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.28.1 to 1.28.2.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](tokio-rs/tokio@tokio-1.28.1...tokio-1.28.2)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump regex from 1.8.2 to 1.8.3 (#986)

Bumps [regex](https://github.com/rust-lang/regex) from 1.8.2 to 1.8.3.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](rust-lang/regex@1.8.2...1.8.3)

---
updated-dependencies:
- dependency-name: regex
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump quote from 1.0.27 to 1.0.28 (#983)

Bumps [quote](https://github.com/dtolnay/quote) from 1.0.27 to 1.0.28.
- [Release notes](https://github.com/dtolnay/quote/releases)
- [Commits](dtolnay/quote@1.0.27...1.0.28)

---
updated-dependencies:
- dependency-name: quote
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump proc-macro2 from 1.0.58 to 1.0.59 (#985)

Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.58 to 1.0.59.
- [Release notes](https://github.com/dtolnay/proc-macro2/releases)
- [Commits](dtolnay/proc-macro2@1.0.58...1.0.59)

---
updated-dependencies:
- dependency-name: proc-macro2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* restrict sign_with_address_and_signature interface (#988)

* changing js bridge

* dryrunresult ok

* submitting extrinsic working

* tiny up code and ui

* formatting

* remove todos

* support tip and mortality

* Prevent bug when reusing type ids in hashing (#1075)

* practice TDD

* implement a hashmap 2-phases approach

* use nicer types

* add test for cache filling

* adjust test

---------

Co-authored-by: James Wilson <[email protected]>

* small adjustment

* Merge branch 'master' into tadeo-hepperle-browser-extension-signing-example

* fix lock file

* tell users how to add Alice account to run signing example

* adjust to PR comments

* fmt

---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: James Wilson <[email protected]>
Co-authored-by: Niklas Adolfsson <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
  • Loading branch information
4 people authored Aug 2, 2023
1 parent 2176ec9 commit dc0aeac
Show file tree
Hide file tree
Showing 14 changed files with 1,140 additions and 430 deletions.
498 changes: 246 additions & 252 deletions examples/wasm-example/Cargo.lock

Large diffs are not rendered by default.

9 changes: 8 additions & 1 deletion examples/wasm-example/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ edition = "2021"
[dependencies]
futures = "0.3.28"
subxt = { path = "../../subxt", default-features = false, features = ["jsonrpsee", "web"], target_arch = "wasm32" }
yew = {version = "0.20.0", features = ["csr"] }
yew = { version = "0.20.0", features = ["csr"] }
web-sys = "0.3.63"
hex = "0.4.3"
yew-router = "0.17.0"
js-sys = "0.3.63"
wasm-bindgen = "0.2.86"
wasm-bindgen-futures = "0.4.36"
anyhow = "1.0.71"
serde = "1.0.163"
serde_json = "1.0.96"
3 changes: 3 additions & 0 deletions examples/wasm-example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,6 @@ Then, in another terminal, run the app locally with:
trunk serve --open
```

# signing example

For the signing example, we use the `@polkadot/extension-dapp` NPM package to talk to wallets loaded as browser extensions. In order to sign and submit the transaction using the `polkadot --dev` node we spawned above, you'll need to create a dev account in your wallet of choice. Use the recovery phrase `bottom drive obey lake curtain smoke basket hold race lonely fit walk` and the derivation path `//Alice` to create a dev account that can be used.
5 changes: 3 additions & 2 deletions examples/wasm-example/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<head>
<meta charset="utf-8" />
<link data-trunk rel="scss" href="index.scss" />
<title>Yew App</title>
<link data-trunk rel="inline" href="index.js" />
<title>Subxt Examples Yew App</title>
</head>
</html>
</html>
89 changes: 89 additions & 0 deletions examples/wasm-example/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/**
* The `@polkadot/extension-dapp` package can be dynamically imported.
* Usually it is wise to use a package manager like npm or yarn to install it as a dependency.
*
* The `getPolkadotJsExtensionMod` closure returns the `@polkadot/extension-dapp` module on demand.
*/
let getPolkadotJsExtensionMod = (() => {
let mod = null;

// initialize `@polkadot/extension-dapp` module on page load
let initPromise = (async () => {
mod = await import(
"https://cdn.jsdelivr.net/npm/@polkadot/[email protected]/+esm"
);
})();

// return a function that waits for initialization to be finished, in case mod is not initialized yet.
return async () => {
if (mod == null) {
await initPromise;
}
return mod;
};
})();

/**
* Queries wallets from browser extensions like Talisman and the Polkadot.js extension for user accounts.
*
* @returns a json string that contains all the accounts that were found.
*/
async function getAccounts() {
const extensionMod = await getPolkadotJsExtensionMod();
await extensionMod.web3Enable("Subxt Example App");
const allAccounts = await extensionMod.web3Accounts();
const accountObjects = allAccounts.map((account) => ({
name: account.meta.name, // e.g. "Alice"
source: account.meta.source, // e.g. "talisman", "polkadot-js"
ty: account.type, // e.g. "sr25519"
address: account.address // e.g. "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"
}));
console.log(accountObjects);
return JSON.stringify(accountObjects);
}

/**
* Signs a payload via browser extension
*
* @param payloadAsStr a string representing a JSON object like this:
* let payload = {
* "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
* };
* @param source the extension used for signing as a string
* @param address the ss58 encoded address as a string
* @returns {Promise<*>}
*/
async function signPayload(payloadAsStr, source, address) {
let payload = JSON.parse(payloadAsStr);
const extensionMod = await getPolkadotJsExtensionMod();
const injector = await extensionMod.web3FromSource(source);
const signPayload = injector?.signer?.signPayload;
if (!!signPayload) {
const {signature} = await signPayload(payload);
console.log("signature js:", signature)
return signature;
} else {
throw "The extension's injector does not have a `signPayload` function on its `signer`";
}
}
151 changes: 98 additions & 53 deletions examples/wasm-example/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,56 +2,101 @@ $primary: #24cc85;
$secondary: #1f624a;
$dark: #242a35;

*{
font-family: monospace;
color: $dark;

}

html{
background-color: $dark;
display: flex;
justify-content: center;
height: 100%;
}

h1{
font-weight: bolder;
color: $dark;
}

body{
width: 800px;
max-width: 100%;
box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
height: 100%;
margin: 0px;
padding: 16px;
background-color: $primary;
}


p{
white-space: pre-wrap;
border-radius: 8px;
padding: 8px;
box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
background-color: $dark;
color: white;
}
button{
font-size: large;
padding: 8px 16px;
font-weight: bold;
background-color: $dark;
border: none;
border-radius: 8px;
color: white;
cursor: pointer;
display: block;
margin-top: 8px;
}

button:hover{
background-color: $secondary;
}
* {
font-family: monospace;
color: $dark;
}

html {
background-color: $dark;
display: flex;
justify-content: center;
height: 100%;
}

h1 {
font-weight: bolder;
color: $dark;
}

body {
width: 800px;
max-width: 100%;
box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
min-height: 100%;
margin: 0px;
padding: 16px;
background-color: $primary;
}

p {
white-space: pre-wrap;
border-radius: 8px;
padding: 8px;
box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
background-color: $dark;
color: white;
}

button {
font-size: large;
padding: 8px 16px;
font-weight: bold;
background-color: $dark;
border: none;
border-radius: 8px;
color: white;
cursor: pointer;
display: block;
margin-top: 8px;
}

a {
text-decoration: none;
}

button:hover {
background-color: $secondary;
}

input {
font-size: large;
background-color: white;
color: $dark;
border-radius: 8px;
padding: 8px;
}

.mb {
margin-bottom: 12px;
}

small {
color: #24cc85;
}

.error {
color: red;
background: black;
padding: 8px;
border-radius: 8px;
}

@keyframes loading {
0% {
transform: translateX(0);
opacity: 1;
}
50% {
transform: translateX(20px);
opacity: 0.5;
}
100% {
transform: translateX(0);
opacity: 1;
}
}

.loading {
animation: loading 0.7s infinite;
}
Loading

0 comments on commit dc0aeac

Please sign in to comment.