fix: WalletConnect multi-chain signing for Asset Hub deposits

This commit is contained in:
2026-02-24 03:14:00 +03:00
parent 402eaf4684
commit 4536c454a4
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);
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 {
await initWalletConnect();
const { uri, approval } = await connectWithQR(genesisHash);
const { uri, approval } = await connectWithQR(genesisHash, additionalHashes);
// Start approval listener in background
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');
// Default genesis hash for signRaw; signPayload auto-detects from TX payload
const genesisHash = pezkuwi.api.genesisHash.toHex();
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
* 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;
approval: () => Promise<SessionTypes.Struct>;
}> {
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] Genesis hash:', genesisHash);
console.warn('[WC] Session proposal chain IDs:', chainIds);
console.warn('[WC] Methods:', POLKADOT_METHODS);
const { uri, approval } = await client.connect({
optionalNamespaces: {
polkadot: {
methods: POLKADOT_METHODS,
chains: [chainId],
chains: chainIds,
events: POLKADOT_EVENTS,
},
},
@@ -182,9 +187,8 @@ export function validateSession(): boolean {
* Create a Signer adapter compatible with @pezkuwi/api's Signer interface
* Routes signPayload and signRaw through WalletConnect
*/
export function createWCSigner(genesisHash: string, address: string) {
const chainId = buildChainId(genesisHash);
const wcAccount = `polkadot:${chainId.split(':')[1]}:${address}`;
export function createWCSigner(defaultGenesisHash: string, address: string) {
const defaultChainId = buildChainId(defaultGenesisHash);
return {
signPayload: async (payload: {
@@ -211,6 +215,15 @@ export function createWCSigner(genesisHash: string, address: string) {
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 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.');
}
const wcAccount = `polkadot:${defaultChainId.split(':')[1]}:${address}`;
const id = ++requestId;
const result = await signClient.request<{ signature: string }>({
topic: currentSession.topic,
chainId,
chainId: defaultChainId,
request: {
method: 'polkadot_signMessage',
params: {