Skip to content

Commit

Permalink
almost working
Browse files Browse the repository at this point in the history
  • Loading branch information
rossbulat committed Nov 22, 2024
1 parent f59cffc commit a2c3ffa
Show file tree
Hide file tree
Showing 2 changed files with 158 additions and 1 deletion.
24 changes: 23 additions & 1 deletion packages/app/src/hooks/useSubmitExtrinsic/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ import type {
VaultSignatureResult,
VaultSignStatus,
} from 'library/Signers/VaultSigner/types';
import { WallectConnectSigner } from 'library/Signers/WallectConnectSigner';
import { useApi } from 'contexts/Api';
import { useWalletConnect } from 'contexts/WalletConnect';

export const useSubmitExtrinsic = ({
tx,
Expand All @@ -47,7 +50,9 @@ export const useSubmitExtrinsic = ({
network,
networkData: { units, unit },
} = useNetwork();
const { chainSpecs } = useApi();
const { getNonce } = useBalances();
const { signWcTx } = useWalletConnect();
const { activeProxy } = useActiveAccounts();
const { extensionsStatus } = useExtensions();
const { isProxySupported } = useProxySupported();
Expand Down Expand Up @@ -136,6 +141,8 @@ export const useSubmitExtrinsic = ({

// Extrinsic submission handler.
const onSubmit = async () => {
const { pApi } = ApiController.get(network);

const account = getAccount(fromRef.current);
if (account === null || submitting || !shouldSubmit) {
return;
Expand Down Expand Up @@ -240,6 +247,10 @@ export const useSubmitExtrinsic = ({
decimals: units,
tokenSymbol: unit,
};
const blockNumber = await pApi.query.System.Number.getValue();
const blockHash = await pApi.query.System.BlockHash.getValue(
blockNumber - 1
);

switch (source) {
case 'ledger':
Expand Down Expand Up @@ -274,7 +285,16 @@ export const useSubmitExtrinsic = ({
break;

case 'wallet_connect':
// TODO: Implement
signer = await new WallectConnectSigner(
pubKey,
`polkadot:${chainSpecs.genesisHash.substring(2).substring(0, 32)}`,
signWcTx,
chainSpecs,
Number(nonce),
fromRef.current,
blockNumber,
blockHash.asHex()
).getPolkadotSigner();
break;
}
} else {
Expand Down Expand Up @@ -302,13 +322,15 @@ export const useSubmitExtrinsic = ({
}
},
error: (err: Error) => {
console.log(err);
if (err instanceof InvalidTxError) {
onFailedTx();
}
sub?.unsubscribe();
},
});
} catch (e) {
console.log(e);
onError('default');
}
};
Expand Down
135 changes: 135 additions & 0 deletions packages/app/src/library/Signers/WallectConnectSigner/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// Copyright 2024 @polkadot-cloud/polkadot-staking-dashboard authors & contributors
// SPDX-License-Identifier: GPL-3.0-only

import { createV4Tx, getSignBytes } from '@polkadot-api/signers-common';
import type { V15 } from '@polkadot-api/substrate-bindings';
import {
Binary,
compact,
decAnyMetadata,
u32,
} from '@polkadot-api/substrate-bindings';
import type { WalletConnectSignTx } from 'contexts/WalletConnect/types';
import type { PapiChainSpec } from 'model/Api/types';
import type { PolkadotSigner } from 'polkadot-api';
import { toHex } from 'polkadot-api/utils';

export class WallectConnectSigner {
#publicKey: Uint8Array;
#who: string;
#caip: string;
#signFn: WalletConnectSignTx;
#chainSpecs: PapiChainSpec;
#nonce: number;
#blockNumber: number;
#blockHash: string;

constructor(
pubKey: Uint8Array,
caip: string,
signFn: WalletConnectSignTx,
chainSpecs: PapiChainSpec,
nonce: number,
who: string,
blockNumber: number,
blockHash: string
) {
this.#publicKey = pubKey;
this.#caip = caip;
this.#signFn = signFn;
this.#chainSpecs = chainSpecs;
this.#who = who;
this.#nonce = nonce;
this.#blockNumber = blockNumber;
this.#blockHash = blockHash;
}

#toPjsHex(value: number | bigint, minByteLen?: number) {
let inner = value.toString(16);
inner = (inner.length % 2 ? '0' : '') + inner;
const nPaddedBytes = Math.max(0, (minByteLen || 0) - inner.length / 2);
return '0x' + '00'.repeat(nPaddedBytes) + inner;
}

async getPolkadotSigner(): Promise<PolkadotSigner> {
const signTx: PolkadotSigner['signTx'] = async (
callData,
signedExtensions,
metadata
) => {
const v15 = decAnyMetadata(metadata).metadata.value as unknown as V15;
const identifiers: string[] = [];
const extra: Uint8Array[] = [];
const additionalSigned: Uint8Array[] = [];
v15.extrinsic.signedExtensions.map(({ identifier }) => {
const signedExtension = signedExtensions[identifier];
if (!signedExtension) {
throw new Error(`Missing ${identifier} signed extension`);
}
identifiers.push(identifier);
extra.push(signedExtension.value);
additionalSigned.push(signedExtension.additionalSigned);
});

const { version } = v15.extrinsic;
const lastBlock = this.#blockNumber - 1;
// const phase = lastBlock % 64;
// const period = 6;
// const era = toHex(new Uint8Array([phase, period]));

const unsignedTransaction = {
specVersion: this.#toPjsHex(
u32.dec(u32.enc(this.#chainSpecs.specVersion)),
4
),
transactionVersion: this.#toPjsHex(
u32.dec(u32.enc(this.#chainSpecs.transactionVersion))
),
version,
address: this.#who,
blockHash: this.#blockHash,
blockNumber: this.#toPjsHex(u32.dec(u32.enc(lastBlock)), 4),
era: '0x00',
genesisHash: this.#chainSpecs.genesisHash,
method: toHex(callData),
nonce: this.#toPjsHex(compact.dec(compact.enc(this.#nonce)), 4),
signedExtensions: identifiers,
tip: this.#toPjsHex(u32.dec(u32.enc(0)), 16),
};

// Await signature from Wallet Connect.
const signature = await this.#signFn(
this.#caip,
unsignedTransaction,
this.#who
);

console.log(signature);

if (signature === null) {
throw 'Invalid signature';
}
return createV4Tx(
v15,
this.#publicKey,
Binary.fromHex(signature).asBytes(),
extra,
callData
);
};

return {
publicKey: this.#publicKey,
signTx,
signBytes: getSignBytes(async (x) => {
const signatureHex = await this.#signFn(this.#caip, x, this.#who);
if (!signatureHex) {
throw 'Invalid signature';
}
// NOTE: the signature includes a "0x00" at the beginning, indicating a ed25519 signature.
// this is not needed for non-extrinsic signatures.
return Binary.fromHex(signatureHex).asBytes().subarray(1);
}),
};
}
}

0 comments on commit a2c3ffa

Please sign in to comment.