Skip to content

Commit

Permalink
basic wc recover signature
Browse files Browse the repository at this point in the history
  • Loading branch information
bh2smith committed May 13, 2024
1 parent 721a2df commit b258721
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 1 deletion.
50 changes: 50 additions & 0 deletions src/chains/ethereum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ import {
NearContractFunctionPayload,
TxPayload,
TransactionWithSignature,
MPCSignature,
RecoveryData,
MessageData,
TypedMessageData,
} from "../types/types";
import { MultichainContract } from "../mpcContract";
import { buildTxPayload, addSignature, populateTx } from "../utils/transaction";
Expand Down Expand Up @@ -251,6 +255,52 @@ export class NearEthAdapter {
];
}

async recoverSignature(
recoveryData: RecoveryData,
signatureData: MPCSignature
): Promise<Hex> {
const { big_r, big_s } = signatureData;
if (recoveryData.type === "eth_sendTransaction") {
return addSignature(
{ transaction: recoveryData.data as Hex, signature: signatureData },
this.address
);
}
const r = `0x${big_r.substring(2)}` as Hex;
const s = `0x${big_s}` as Hex;
const sigs: [Hex, Hex] = [
serializeSignature({ r, s, yParity: 0 }),
serializeSignature({ r, s, yParity: 1 }),
];
let validity: [boolean, boolean];
if (recoveryData.type === "personal_sign") {
validity = await Promise.all([
verifyMessage({
signature: sigs[0],
...(recoveryData.data as MessageData),
}),
verifyMessage({
signature: sigs[1],
...(recoveryData.data as MessageData),
}),
]);
} else if (recoveryData.type === "eth_signTypedData") {
validity = await Promise.all([
verifyTypedData({
signature: sigs[0],
...(recoveryData.data as TypedMessageData),
}),
verifyTypedData({
signature: sigs[1],
...(recoveryData.data as TypedMessageData),
}),
]);
} else {
throw new Error("Invalid Path");
}
return pickValidSignature(validity, sigs);
}

/// Mintbase Wallet
async handleSessionRequest(request: Web3WalletTypes.SessionRequest): Promise<{
evmMessage: string | TransactionSerializable;
Expand Down
23 changes: 22 additions & 1 deletion src/types/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { MultichainContract } from "../mpcContract";
import { FunctionCallAction } from "@near-wallet-selector/core";
import { Hex } from "viem";
import { Hex, SignableMessage } from "viem";

export interface BaseTx {
/// Recipient of the transaction
Expand Down Expand Up @@ -67,6 +67,27 @@ export interface MPCSignature {
big_s: string;
}

export interface MessageData {
address: Hex;
message: SignableMessage;
}

export interface TypedMessageData {
address: Hex;
/* eslint-disable @typescript-eslint/no-explicit-any */
types: any;
primaryType: any;
message: any;
domain: any;
/* eslint-enable @typescript-eslint/no-explicit-any */
}

export interface RecoveryData {
// TODO use enum!
type: string;
data: MessageData | TypedMessageData | Hex;
}

/**
* Sufficient data required to construct a signed Ethereum Transaction.
*/
Expand Down
23 changes: 23 additions & 0 deletions src/wallet-connect/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
serializeTransaction,
} from "viem";
import { populateTx, toPayload } from "../utils/transaction";
import { RecoveryData } from "../types/types";

// Interface for Ethereum transaction parameters
export interface EthTransactionParams {
Expand Down Expand Up @@ -36,6 +37,7 @@ export async function wcRouter(
): Promise<{
evmMessage: TransactionSerializable | string;
payload: number[];
signatureRecoveryData: RecoveryData;
}> {
switch (method) {
// I believe {personal,eth}_sign both get routed to the same place.
Expand All @@ -47,6 +49,13 @@ export async function wcRouter(
return {
evmMessage: fromHex(messageHash, "string"),
payload: toPayload(hashMessage(messageHash)),
signatureRecoveryData: {
type: "personal_sign",
data: {
address: sender,
message: messageHash,
},
},
};
}
case "eth_sendTransaction": {
Expand All @@ -64,6 +73,10 @@ export async function wcRouter(
return {
payload: toPayload(keccak256(serializeTransaction(transaction))),
evmMessage: transaction,
signatureRecoveryData: {
type: "eth_sendTransaction",
data: serializeTransaction(transaction),
},
};
}
case "eth_signTypedData":
Expand All @@ -76,6 +89,16 @@ export async function wcRouter(
return {
evmMessage: dataString,
payload: toPayload(hashTypedData(typedData)),
signatureRecoveryData: {
type: "eth_signTypedData",
data: {
address: sender,
types: typedData.types,
primaryType: typedData.primaryType,
message: typedData.message,
domain: typedData.domain,
},
},
};
}
}
Expand Down

0 comments on commit b258721

Please sign in to comment.