@abstract-foundation/agw-client
Version:
Abstract Global Wallet Client SDK
69 lines • 3.8 kB
JavaScript
import { BaseError, fromRlp, hashTypedData, } from 'viem';
import {} from 'viem/accounts';
import { EOA_VALIDATOR_ADDRESS, SESSION_KEY_VALIDATOR_ADDRESS, } from '../constants.js';
import { getAgwTypedSignature } from '../getAgwTypedSignature.js';
import { encodeSessionWithPeriodIds, getPeriodIdsForTransaction, } from '../sessions.js';
import { isEip712TypedData, transformEip712TypedData } from '../utils.js';
import { sendPrivySignTypedData } from './sendPrivyTransaction.js';
import { signEip712TransactionInternal, signTransaction, } from './signTransaction.js';
export async function signTypedData(client, signerClient, publicClient, parameters, isPrivyCrossApp = false) {
// if the typed data is already a zkSync EIP712 transaction, don't try to transform it
// to an AGW typed signature, just pass it through to the signer.
if (isEip712TypedData(parameters)) {
const transformedTypedData = transformEip712TypedData(parameters);
if (transformedTypedData.chainId !== client.chain.id) {
throw new BaseError('Chain ID mismatch in AGW typed signature');
}
const signedTransaction = await signTransaction(client, signerClient, publicClient, {
...transformedTypedData,
chain: client.chain,
}, EOA_VALIDATOR_ADDRESS, {}, undefined, isPrivyCrossApp);
if (!signedTransaction.startsWith('0x71')) {
throw new BaseError('Expected RLP encoded EIP-712 transaction as signature');
}
const rlpSignature = `0x${signedTransaction.slice(4)}`;
const signatureParts = fromRlp(rlpSignature, 'hex');
if (signatureParts.length < 15) {
throw new BaseError('Expected RLP encoded EIP-712 transaction with at least 15 fields');
}
// This is somewhat not type safe as it assumes that the signature from signTransaction is an
// RLP encoded 712 transaction and that the customSignature field is the 15th field in the transaction.
// That being said, it's a safe assumption for the current use case.
return signatureParts[14];
}
else if (isPrivyCrossApp) {
return await sendPrivySignTypedData(client, parameters);
}
return await getAgwTypedSignature({
client,
signer: signerClient,
messageHash: hashTypedData(parameters),
});
}
export async function signTypedDataForSession(client, signerClient, publicClient, parameters, session, paymasterHandler) {
// if the typed data is already a zkSync EIP712 transaction, don't try to transform it
// to an AGW typed signature, just pass it through to the signer.
if (!isEip712TypedData(parameters)) {
throw new BaseError('Session client can only sign EIP712 transactions as typed data');
}
const transactionRequest = transformEip712TypedData(parameters);
if (!transactionRequest.to) {
throw new BaseError('Transaction must have a to address');
}
// Match the expect signature format of the AGW smart account so the result can be
// directly used in eth_sendRawTransaction as the customSignature field
const validationHookData = {
[SESSION_KEY_VALIDATOR_ADDRESS]: encodeSessionWithPeriodIds(session, getPeriodIdsForTransaction({
sessionConfig: session,
target: transactionRequest.to,
selector: (transactionRequest.data?.slice(0, 10) ?? '0x'),
timestamp: BigInt(Math.floor(Date.now() / 1000)),
})),
};
const { customSignature } = await signEip712TransactionInternal(client, signerClient, publicClient, {
chain: client.chain,
...transactionRequest,
}, SESSION_KEY_VALIDATOR_ADDRESS, validationHookData, paymasterHandler);
return customSignature;
}
//# sourceMappingURL=signTypedData.js.map