diff --git a/patches/@polkahub__pjs-wallet@0.9.1.patch b/patches/@polkahub__pjs-wallet@0.9.1.patch
new file mode 100644
index 0000000..c18483d
--- /dev/null
+++ b/patches/@polkahub__pjs-wallet@0.9.1.patch
@@ -0,0 +1,89 @@
+diff --git a/dist/ManagePjsWallet.js b/dist/ManagePjsWallet.js
+index ec891b30a0bda8eb60b0ec647262ad334c04db89..03c93af0448018b58ef8abc2395e56b330d64038 100644
+--- a/dist/ManagePjsWallet.js
++++ b/dist/ManagePjsWallet.js
+@@ -4,38 +4,16 @@ import { cn, SourceButton } from '@polkahub/ui-components';
+ import { state, useStateObservable } from '@react-rxjs/core';
+ import { CircleQuestionMark } from 'lucide-react';
+ import { filter, switchMap } from 'rxjs';
+-import nova from './assets/nova.webp.js';
+-import pjs from './assets/pjs.webp.js';
+-import subwallet from './assets/subwallet.webp.js';
+-import talisman from './assets/talisman.webp.js';
+-import polkagate from './assets/polkagate.webp.js';
+-import fearless from './assets/fearless.webp.js';
++import blackbeard from './assets/blackbeard.svg.js';
+ import { pjsWalletProviderId } from './provider.js';
+
++// Only extensions that sign ML-DSA are listed: the Quantus runtime accepts no
++// other signature, so offering polkadot{.js}, Talisman and the rest would
++// connect wallets that can never sign here. Patched in qapi.
+ const knownExtensions = {
+- "polkadot-js": {
+- name: "Polkadot JS",
+- logo: pjs
+- },
+- "nova-wallet": {
+- name: "Nova Wallet",
+- logo: nova
+- },
+- talisman: {
+- name: "Talisman",
+- logo: talisman
+- },
+- "subwallet-js": {
+- name: "Subwallet",
+- logo: subwallet
+- },
+- polkagate: {
+- name: "Polkagate",
+- logo: polkagate
+- },
+- "fearless-wallet": {
+- name: "Fearless Wallet",
+- logo: fearless
++ blackbeard: {
++ name: "blackbeard",
++ logo: blackbeard
+ }
+ };
+ const [pjsWalletPlugin$, useExternalizedPlugin] = externalizePlugin(pjsWalletProviderId);
+diff --git a/dist/assets/blackbeard.svg.js b/dist/assets/blackbeard.svg.js
+new file mode 100644
+index 0000000000000000000000000000000000000000..4dfb32200a16b6c32b258d0519cd6c820a3bf9ab
+--- /dev/null
++++ b/dist/assets/blackbeard.svg.js
+@@ -0,0 +1,4 @@
++// blackbeard's sigil, the Quantus post-quantum wallet (quantus/extension#15)
++var blackbeard = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MCA0MCIgd2lkdGg9IjQwIiBoZWlnaHQ9IjQwIj4KICA8IS0tIGJsYWNrYmVhcmQub2JzZXJ2ZXIncyBzaWdpbCwgY2VudHJlZCBvbiBhIHNxdWFyZSBmb3IgaWNvbnMgLS0+CiAgPHJlY3Qgd2lkdGg9IjQwIiBoZWlnaHQ9IjQwIiByeD0iNiIgZmlsbD0iIzBkMGIwOSIvPgogIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDMgMCkiPgogICAgPHBhdGggZD0iTTE3IDEgTDMyIDcgVjIwIEMzMiAyOSAyNSAzNSAxNyAzOSBDOSAzNSAyIDI5IDIgMjAgVjcgWiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjYmQ4ODI5IiBzdHJva2Utd2lkdGg9IjEuNiIvPgogICAgPHBhdGggZD0iTTE3IDggTDI0IDEyIFYyMSBDMjQgMjYgMjAuNSAyOS41IDE3IDMxLjUgQzEzLjUgMjkuNSAxMCAyNiAxMCAyMSBWMTIgWiIgZmlsbD0iI2JkODgyOTIyIi8+CiAgICA8cGF0aCBkPSJNMTcgMTEgVjI4IiBzdHJva2U9IiNkODQ1M2EiIHN0cm9rZS13aWR0aD0iMS42Ii8+CiAgICA8cGF0aCBkPSJNMTMgMTUgTDE3IDExIEwyMSAxNSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZDg0NTNhIiBzdHJva2Utd2lkdGg9IjEuNiIvPgogIDwvZz4KPC9zdmc+Cg==";
++
++export { blackbeard as default };
+diff --git a/dist/provider.js b/dist/provider.js
+index a0a44532893fc9b9b3d9c449c40362e60cfa3b95..d8f90bf491ea5fc4f708d456d2c3037255bc6dc8 100644
+--- a/dist/provider.js
++++ b/dist/provider.js
+@@ -6,6 +6,10 @@ import { getSs58AddressInfo } from 'polkadot-api';
+ import { concat, timer, map, filter, take, interval, switchMap, defer, retry, fromEventPattern, startWith, catchError, tap, ignoreElements, NEVER, shareReplay, firstValueFrom, scan } from 'rxjs';
+
+ const pjsWalletProviderId = "pjs-wallet";
++// Patched in qapi: only extensions that can sign for a post-quantum chain are
++// offered or connected. Anything else injected into the page is ignored.
++const PQ_EXTENSIONS = ["blackbeard"];
++const getPqExtensions = () => getInjectedExtensions().filter((name) => PQ_EXTENSIONS.includes(name));
+ const createPjsWalletProvider = (opts) => {
+ const { persist, accountFormat } = {
+ persist: localStorageProvider("pjs-wallet-plugin"),
+@@ -15,11 +19,11 @@ const createPjsWalletProvider = (opts) => {
+ const availableExtensions$ = state(
+ concat(
+ timer(0, 100).pipe(
+- map(getInjectedExtensions),
++ map(getPqExtensions),
+ filter((v) => v.length > 0),
+ take(1)
+ ),
+- interval(2e3).pipe(map(getInjectedExtensions))
++ interval(2e3).pipe(map(getPqExtensions))
+ ),
+ []
+ );
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index cf2b7dd..0ad3d7e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -8,6 +8,7 @@ patchedDependencies:
'@polkadot-api/signers-common': 365a34617de2ae3ad2f7e009f7f3e20e0078448fbfc93c395d323f0e21b75d37
'@polkadot-api/substrate-bindings@0.21.0': 44a839dff72a3f1f9334c05ea6c72f29757e5d7168e8fee564f12de216710537
'@polkadot-api/substrate-bindings@0.21.1': 44a839dff72a3f1f9334c05ea6c72f29757e5d7168e8fee564f12de216710537
+ '@polkahub/pjs-wallet@0.9.1': f359348c980dcf8a9f7077a067ffbc79e23c166172a4fa1be36de5340072104d
react18-json-view: 962696fac5fe7ad3e94fd36dad07521c6c3eafd52f219ab335d52438387f6b66
importers:
@@ -5741,7 +5742,7 @@ snapshots:
- supports-color
- utf-8-validate
- '@polkahub/pjs-wallet@0.9.1(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(esbuild@0.28.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
+ '@polkahub/pjs-wallet@0.9.1(patch_hash=f359348c980dcf8a9f7077a067ffbc79e23c166172a4fa1be36de5340072104d)(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(esbuild@0.28.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
dependencies:
'@polkadot-api/pjs-signer': 0.8.0(rxjs@7.8.2)
'@polkahub/context': 0.9.1(@types/react@19.2.18)(esbuild@0.28.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
@@ -9288,7 +9289,7 @@ snapshots:
'@polkahub/context': 0.9.1(@types/react@19.2.18)(esbuild@0.28.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@polkahub/ledger': 0.9.1(@ledgerhq/hw-transport@6.35.5)(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(esbuild@0.28.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@polkahub/multisig': 0.9.1(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(esbuild@0.28.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
- '@polkahub/pjs-wallet': 0.9.1(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(esbuild@0.28.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
+ '@polkahub/pjs-wallet': 0.9.1(patch_hash=f359348c980dcf8a9f7077a067ffbc79e23c166172a4fa1be36de5340072104d)(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(esbuild@0.28.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@polkahub/plugin': 0.9.1(@react-rxjs/core@0.10.8(react@19.2.8)(rxjs@7.8.2))(esbuild@0.28.1)(react@19.2.8)
'@polkahub/proxy': 0.9.1(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(esbuild@0.28.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@polkahub/read-only': 0.9.1(@types/react-dom@19.2.7(@types/react@19.2.18))(@types/react@19.2.18)(esbuild@0.28.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index 0c3647a..8aedb0b 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -18,4 +18,5 @@ patchedDependencies:
# and patched too so a minor bump does not silently drop the fix.
'@polkadot-api/substrate-bindings@0.21.0': patches/@polkadot-api__substrate-bindings@0.21.0.patch
'@polkadot-api/substrate-bindings@0.21.1': patches/@polkadot-api__substrate-bindings@0.21.1.patch
+ '@polkahub/pjs-wallet@0.9.1': patches/@polkahub__pjs-wallet@0.9.1.patch
react18-json-view: patches/react18-json-view.patch
diff --git a/src/App.tsx b/src/App.tsx
index 8ffbaf1..b9ff199 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,4 +1,3 @@
-import { VaultTxModal } from "polkahub"
import { lazy } from "react"
import { Navigate, Route, Routes } from "react-router-dom"
import { ConnectionState } from "./components/ConnectionState"
@@ -35,7 +34,6 @@ export default function App() {
} />
-
)
diff --git a/src/main.tsx b/src/main.tsx
index 0561f70..2892b43 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -1,6 +1,6 @@
import { dynamicBuilder$, getDefaultChain } from "@/state/chains/chain.state"
import { RemoveSubscribe, Subscribe } from "@react-rxjs/core"
-import { MultisigExternalSignerModal, PolkaHubProvider } from "polkahub"
+import { PolkaHubProvider } from "polkahub"
import { StrictMode } from "react"
import { createRoot } from "react-dom/client"
import { BrowserRouter } from "react-router-dom"
@@ -43,7 +43,6 @@ createRoot(document.getElementById("root")!).render(
-
diff --git a/src/pages/Accounts/AccountList.tsx b/src/pages/Accounts/AccountList.tsx
index b1b69f8..2c30499 100644
--- a/src/pages/Accounts/AccountList.tsx
+++ b/src/pages/Accounts/AccountList.tsx
@@ -16,12 +16,9 @@ import { CompatibilityLevel, SS58String } from "polkadot-api"
import { toHex } from "polkadot-api/utils"
import {
Account,
- ledgerProviderId,
PjsWalletAccount,
- polkadotVaultProviderId,
readOnlyProviderId,
useAvailableAccounts,
- walletConnectProviderId,
} from "polkahub"
import { FC } from "react"
import {
@@ -34,15 +31,11 @@ import {
const knownGroupsNames: Record = {
"pjs-wallet": "Browser Extensions",
- [ledgerProviderId]: "Ledger",
[readOnlyProviderId]: "Read Only",
- [polkadotVaultProviderId]: "Polkadot Vault",
- [walletConnectProviderId]: "Wallet Connect",
}
const knownGroupsColors: Record = {
"pjs-wallet": "var(--color-lime-700)",
[readOnlyProviderId]: "var(--color-orange-700)",
- [walletConnectProviderId]: "var(--color-blue-700)",
}
export const AccountList = () => {
@@ -96,10 +89,6 @@ const AccountCard: FC<{
}
export const knownExtensions: Record = {
blackbeard: "blackbeard",
- "polkadot-js": "Polkadot JS",
- "nova-wallet": "Nova Wallet",
- talisman: "Talisman",
- "subwallet-js": "Subwallet",
}
const getExtensionName = (id: string) => knownExtensions[id] ?? id
const getGroupName = (id: string) => knownGroupsNames[id] ?? id
diff --git a/src/pages/Accounts/Providers.tsx b/src/pages/Accounts/Providers.tsx
index 0e541ef..542a94c 100644
--- a/src/pages/Accounts/Providers.tsx
+++ b/src/pages/Accounts/Providers.tsx
@@ -8,15 +8,11 @@ import {
} from "@polkahub/ui-components"
import { ChevronLeft } from "lucide-react"
import {
- ManageLedger,
- ManageMultisig,
ManageProxy,
ManageReadOnly,
- ManageVault,
ModalContext,
PjsWalletButtons,
usePolkaHubModalState,
- WalletConnectButton,
} from "polkahub"
import { FC, PropsWithChildren } from "react"
@@ -71,15 +67,9 @@ const ManageToDialog: FC = ({ children }) => {
export const PolkahubModalBasedManagers = () => (
<>
-
>
)
diff --git a/src/pages/Extrinsics/SubmitTx/SubmitTxForm.tsx b/src/pages/Extrinsics/SubmitTx/SubmitTxForm.tsx
index 86cc05c..58c25e2 100644
--- a/src/pages/Extrinsics/SubmitTx/SubmitTxForm.tsx
+++ b/src/pages/Extrinsics/SubmitTx/SubmitTxForm.tsx
@@ -8,10 +8,8 @@ import {
import { FC } from "react"
const groupLabels: Record = {
- ledger: "Ledger",
+ "pjs-wallet": "Browser Extensions",
readonly: "Read Only",
- "polkadot-vault": "Vault",
- walletconnect: "Wallet Connect",
}
export const SelectAccount: FC<{
diff --git a/src/state/polkahub.ts b/src/state/polkahub.ts
index 54662a4..126e08d 100644
--- a/src/state/polkahub.ts
+++ b/src/state/polkahub.ts
@@ -1,20 +1,13 @@
import { polkadot_people } from "@polkadot-api/descriptors"
import { liftSuspense, state, SUSPENSE, withDefault } from "@react-rxjs/core"
import { AccountId, Binary, HexString, SS58String } from "polkadot-api"
-import { WsEvent } from "polkadot-api/ws"
import {
Account,
- createLedgerProvider,
- createMultisigProvider,
createPjsWalletProvider,
- createPolkadotVaultProvider,
createPolkaHub,
createProxyProvider,
createReadOnlyProvider,
createSelectedAccountPlugin,
- createWalletConnectProvider,
- knownChains,
- multisigExternalSigner,
Plugin,
} from "polkahub"
import {
@@ -23,20 +16,15 @@ import {
firstValueFrom,
map,
pipe,
- startWith,
switchMap,
} from "rxjs"
import { chainProperties$ } from "./chain-props.state"
import {
canSetStorage$,
client$,
- currentWsStatus$,
- getChainSource,
- selectedChain$,
unsafeApi$,
} from "./chains/chain.state"
import { identity$, isVerified } from "./identity.state"
-import { WebsocketSource } from "./chains/websocket"
const removeSuspense = () =>
pipe(
@@ -44,23 +32,8 @@ const removeSuspense = () =>
filter((v): v is T => v !== SUSPENSE),
)
-const getNetworkInfo = () =>
- firstValueFrom(
- chainProperties$.pipe(
- removeSuspense(),
- filter((v) => v != null),
- map(({ tokenDecimals, tokenSymbol }) => ({
- decimals: tokenDecimals!,
- tokenSymbol: tokenSymbol!,
- })),
- ),
- )
-
const selectedAccountPlugin = createSelectedAccountPlugin()
const pjsWalletProvider = createPjsWalletProvider()
-const polkadotVaultProvider = createPolkadotVaultProvider({
- getNetworkInfo,
-})
const readOnlyProvider$ = canSetStorage$.pipe(
liftSuspense(),
filter((v) => v !== SUSPENSE),
@@ -70,21 +43,6 @@ const readOnlyProvider$ = canSetStorage$.pipe(
}),
),
)
-const ledgerAccountProvider = createLedgerProvider(async () => {
- const module = await import("@ledgerhq/hw-transport-webusb")
- return module.default.create()
-}, getNetworkInfo)
-const walletConnectProvider = createWalletConnectProvider(
- import.meta.env.VITE_REOWN_PROJECT_ID,
- [
- knownChains.polkadot,
- knownChains.polkadotAh,
- knownChains.kusama,
- knownChains.kusamaAh,
- knownChains.paseo,
- knownChains.paseoAh,
- ],
-)
const proxyProvider = createProxyProvider((address) =>
firstValueFrom(
unsafeApi$.pipe(
@@ -95,61 +53,18 @@ const proxyProvider = createProxyProvider((address) =>
),
),
)
-const multisigProvider$ = selectedChain$.pipe(
- switchMap((chain) =>
- combineLatest([getChainSource(chain), currentWsStatus$]),
- ),
- map(([source, wsStatus]) => {
- if (source.type === "websocket" && source.forkMethod !== "none") {
- return null
- }
-
- if (
- source.type === "chainSpec" &&
- ![
- "polkadot",
- "westend",
- "kusama",
- "paseo",
- "polkadot_asset_hub",
- "westend_asset_hub",
- "kusama_asset_hub",
- "paseo_asset_hub",
- ].includes(source.id)
- ) {
- return null
- }
-
- const getWsUri = (source: WebsocketSource) => {
- if (wsStatus?.type === WsEvent.CONNECTED) return wsStatus.uri
- return typeof source.endpoint === "string"
- ? source.endpoint
- : source.endpoint[0]
- }
-
- const chain =
- source.type === "chainSpec" ? `sm-${source.id}` : `ws-${getWsUri(source)}`
-
- return createMultisigProvider(
- multisigExternalSigner(
- (info, callData) =>
- `https://multisig.usepapi.app/?chain=${chain}&calldata=${callData}&signatories=${info.signatories.join("_")}&threshold=${info.threshold}`,
- ),
- )
- }),
- startWith(null),
-)
-
+// Signers that cannot sign for Quantus are not offered. Polkadot Vault, Ledger
+// and WalletConnect produce sr25519/ed25519/ecdsa signatures, and the external
+// multisig signer hands signing to multisig.usepapi.app; the runtime accepts
+// only ML-DSA. What remains: browser extensions (blackbeard, the only one that
+// signs ML-DSA), read-only accounts, and proxies, which sign through whichever
+// of those they wrap.
export const polkaHub = createPolkaHub(
combineLatest([
[selectedAccountPlugin],
[pjsWalletProvider],
- [polkadotVaultProvider],
readOnlyProvider$,
- [ledgerAccountProvider],
- [walletConnectProvider],
[proxyProvider],
- multisigProvider$,
]).pipe(map((v: (Plugin | null)[]) => v.filter((v) => v != null))),
{
getIdentity: (address) =>