Skip to content

Commit

Permalink
Decode personal_sign Messages for UI (#86)
Browse files Browse the repository at this point in the history
  • Loading branch information
bh2smith authored Oct 24, 2024
1 parent 2dd2cac commit d70507c
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 27 deletions.
68 changes: 41 additions & 27 deletions src/near-safe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -377,35 +377,48 @@ export class NearSafe {
* Decodes transaction data for a given EVM transaction and extracts relevant details.
*
* @param {EvmTransactionData} data - The raw transaction data to be decoded.
* @returns {{ chainId: number; costEstimate: string; transactions: MetaTransaction[] }} - An object containing the chain ID, estimated cost, and a list of decoded meta-transactions.
* @returns {DecodedMultisend} - An object containing the chain ID, estimated cost, and a list of decoded meta-transactions.
*/
decodeTxData(data: EvmTransactionData): DecodedMultisend {
// TODO: data.data may not always parse to UserOperation. We will have to handle the other cases.
const userOp: UserOperation = JSON.parse(data.data);
const { callGasLimit, maxFeePerGas, maxPriorityFeePerGas } = userOp;
const maxGasPrice = BigInt(maxFeePerGas) + BigInt(maxPriorityFeePerGas);
const { args } = decodeFunctionData({
abi: this.safePack.m4337.abi,
data: userOp.callData,
});
try {
const userOp: UserOperation = JSON.parse(data.data);
const { callGasLimit, maxFeePerGas, maxPriorityFeePerGas } = userOp;
const maxGasPrice = BigInt(maxFeePerGas) + BigInt(maxPriorityFeePerGas);
const { args } = decodeFunctionData({
abi: this.safePack.m4337.abi,
data: userOp.callData,
});

// Determine if singular or double!
const transactions = isMultisendTx(args)
? decodeMulti(args[2] as string)
: [
{
to: args[0],
value: args[1],
data: args[2],
operation: args[3],
} as MetaTransaction,
];
return {
chainId: data.chainId,
// This is an upper bound on the gas fees (could be lower)
costEstimate: formatEther(BigInt(callGasLimit) * maxGasPrice),
transactions,
};
// Determine if singular or double!
const transactions = isMultisendTx(args)
? decodeMulti(args[2] as string)
: [
{
to: args[0],
value: args[1],
data: args[2],
operation: args[3],
} as MetaTransaction,
];
return {
chainId: data.chainId,
// This is an upper bound on the gas fees (could be lower)
costEstimate: formatEther(BigInt(callGasLimit) * maxGasPrice),
transactions,
};
} catch (error: unknown) {
if (error instanceof SyntaxError) {
return {
chainId: data.chainId,
costEstimate: "0",
transactions: [],
message: data.data,
};
} else {
const message = error instanceof Error ? error.message : String(error);
throw new Error(`decodeTxData: Unexpected error - ${message}`);
}
}
}

/**
Expand Down Expand Up @@ -450,7 +463,8 @@ export class NearSafe {
const [messageHash, _] = params as PersonalSignParams;
const message = decodeSafeMessage(messageHash, safeInfo);
return {
evmMessage: message.safeMessageMessage,
// TODO(bh2smith) this is a bit of a hack.
evmMessage: message.decodedMessage as string,
payload: toPayload(message.safeMessageHash),
hash: message.safeMessageHash,
};
Expand Down
2 changes: 2 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,8 @@ export interface DecodedMultisend {
costEstimate: string;
/** The list of meta-transactions included in the multisend. */
transactions: MetaTransaction[];
/** Raw Message to sign if no transactions present. */
message?: string;
}

/**
Expand Down
39 changes: 39 additions & 0 deletions tests/e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,43 @@ describe("Near Safe Requests", () => {
})
).resolves.not.toThrow();
});

it("adapter: decodeTxData", async () => {
// setup:
const chainId = 11155111;
const expectedMessage =
"Welcome to OpenSea!\n" +
"\n" +
"Click to sign in and accept the OpenSea Terms of Service (https://opensea.io/tos) and Privacy Policy (https://opensea.io/privacy).\n" +
"\n" +
"This request will not trigger a blockchain transaction or cost any gas fees.\n" +
"\n" +
"Wallet address:\n" +
"0xf057e37024abe7e6bc04fb4f00978613b5ca0241\n" +
"\n" +
"Nonce:\n" +
"aca09a1c-a800-4d71-98ed-547f7c59370c";

const signRequest = await adapter.encodeSignRequest({
method: "personal_sign",
chainId,
params: [
"0x57656c636f6d6520746f204f70656e536561210a0a436c69636b20746f207369676e20696e20616e642061636365707420746865204f70656e536561205465726d73206f662053657276696365202868747470733a2f2f6f70656e7365612e696f2f746f732920616e64205072697661637920506f6c696379202868747470733a2f2f6f70656e7365612e696f2f70726976616379292e0a0a5468697320726571756573742077696c6c206e6f742074726967676572206120626c6f636b636861696e207472616e73616374696f6e206f7220636f737420616e792067617320666565732e0a0a57616c6c657420616464726573733a0a3078663035376533373032346162653765366263303466623466303039373836313362356361303234310a0a4e6f6e63653a0a61636130396131632d613830302d346437312d393865642d353437663763353933373063",
"0xf057e37024abe7e6bc04fb4f00978613b5ca0241",
],
});

expect(signRequest.evmData).toStrictEqual({
chainId,
hash: "0xb3a14f9bd21518d7da23dba01ddf7c7ef45795ca1515f1b41b6f3455c862e22d",
data: expectedMessage,
});

expect(adapter.decodeTxData(signRequest.evmData)).toStrictEqual({
chainId: 11155111,
costEstimate: "0",
transactions: [],
message: expectedMessage,
});
});
});

0 comments on commit d70507c

Please sign in to comment.