fix: WalletConnect multi-chain signing for Asset Hub deposits

This commit is contained in:
2026-02-24 03:14:00 +03:00
parent b1de3cc017
commit 42bb4140f2
3 changed files with 30 additions and 10 deletions
+6 -1
View File
@@ -496,9 +496,14 @@ export const PezkuwiProvider: React.FC<PezkuwiProviderProps> = ({
setError(null); setError(null);
const genesisHash = api.genesisHash.toHex(); const genesisHash = api.genesisHash.toHex();
// Include Asset Hub and People Chain in WC session so cross-chain TX signing works
const additionalHashes: string[] = [];
if (assetHubApi?.isConnected) additionalHashes.push(assetHubApi.genesisHash.toHex());
if (peopleApi?.isConnected) additionalHashes.push(peopleApi.genesisHash.toHex());
try { try {
await initWalletConnect(); await initWalletConnect();
const { uri, approval } = await connectWithQR(genesisHash); const { uri, approval } = await connectWithQR(genesisHash, additionalHashes);
// Start approval listener in background // Start approval listener in background
approval().then((session) => { approval().then((session) => {
+1
View File
@@ -263,6 +263,7 @@ export const WalletProvider: React.FC<{ children: React.ReactNode }> = ({ childr
} }
if (import.meta.env.DEV) console.log('[WC] Using WalletConnect for transaction signing'); if (import.meta.env.DEV) console.log('[WC] Using WalletConnect for transaction signing');
// Default genesis hash for signRaw; signPayload auto-detects from TX payload
const genesisHash = pezkuwi.api.genesisHash.toHex(); const genesisHash = pezkuwi.api.genesisHash.toHex();
const wcSigner = createWCSigner(genesisHash, pezkuwi.selectedAccount.address); const wcSigner = createWCSigner(genesisHash, pezkuwi.selectedAccount.address);
+23 -9
View File
@@ -91,22 +91,27 @@ export function buildChainId(genesisHash: string): string {
* Start a WalletConnect pairing session * Start a WalletConnect pairing session
* Returns the URI for QR code display * Returns the URI for QR code display
*/ */
export async function connectWithQR(genesisHash: string): Promise<{ export async function connectWithQR(genesisHash: string, additionalGenesisHashes?: string[]): Promise<{
uri: string; uri: string;
approval: () => Promise<SessionTypes.Struct>; approval: () => Promise<SessionTypes.Struct>;
}> { }> {
const client = await initWalletConnect(); const client = await initWalletConnect();
const chainId = buildChainId(genesisHash); const chainIds = [buildChainId(genesisHash)];
if (additionalGenesisHashes) {
for (const gh of additionalGenesisHashes) {
const cid = buildChainId(gh);
if (!chainIds.includes(cid)) chainIds.push(cid);
}
}
console.warn('[WC] Session proposal chain ID:', chainId); console.warn('[WC] Session proposal chain IDs:', chainIds);
console.warn('[WC] Genesis hash:', genesisHash);
console.warn('[WC] Methods:', POLKADOT_METHODS); console.warn('[WC] Methods:', POLKADOT_METHODS);
const { uri, approval } = await client.connect({ const { uri, approval } = await client.connect({
optionalNamespaces: { optionalNamespaces: {
polkadot: { polkadot: {
methods: POLKADOT_METHODS, methods: POLKADOT_METHODS,
chains: [chainId], chains: chainIds,
events: POLKADOT_EVENTS, events: POLKADOT_EVENTS,
}, },
}, },
@@ -182,9 +187,8 @@ export function validateSession(): boolean {
* Create a Signer adapter compatible with @pezkuwi/api's Signer interface * Create a Signer adapter compatible with @pezkuwi/api's Signer interface
* Routes signPayload and signRaw through WalletConnect * Routes signPayload and signRaw through WalletConnect
*/ */
export function createWCSigner(genesisHash: string, address: string) { export function createWCSigner(defaultGenesisHash: string, address: string) {
const chainId = buildChainId(genesisHash); const defaultChainId = buildChainId(defaultGenesisHash);
const wcAccount = `polkadot:${chainId.split(':')[1]}:${address}`;
return { return {
signPayload: async (payload: { signPayload: async (payload: {
@@ -211,6 +215,15 @@ export function createWCSigner(genesisHash: string, address: string) {
throw new Error('WalletConnect session expired. Please reconnect your wallet.'); throw new Error('WalletConnect session expired. Please reconnect your wallet.');
} }
// Derive chainId from the payload's own genesisHash (set by the TX's API)
// This ensures Asset Hub TXs use Asset Hub chainId, relay TXs use relay chainId, etc.
const chainId = payload.genesisHash ? buildChainId(payload.genesisHash) : defaultChainId;
const wcAccount = `polkadot:${chainId.split(':')[1]}:${address}`;
if (import.meta.env.DEV) {
console.log('[WC] signPayload chainId:', chainId, 'from payload genesis:', payload.genesisHash);
}
const id = ++requestId; const id = ++requestId;
const result = await signClient.request<{ signature: string }>({ const result = await signClient.request<{ signature: string }>({
@@ -246,11 +259,12 @@ export function createWCSigner(genesisHash: string, address: string) {
throw new Error('WalletConnect session expired. Please reconnect your wallet.'); throw new Error('WalletConnect session expired. Please reconnect your wallet.');
} }
const wcAccount = `polkadot:${defaultChainId.split(':')[1]}:${address}`;
const id = ++requestId; const id = ++requestId;
const result = await signClient.request<{ signature: string }>({ const result = await signClient.request<{ signature: string }>({
topic: currentSession.topic, topic: currentSession.topic,
chainId, chainId: defaultChainId,
request: { request: {
method: 'polkadot_signMessage', method: 'polkadot_signMessage',
params: { params: {