Skip to main content

Signing within a Lit Action

Overview

When signing a transaction with Lit, signature shares are typically combined client-side. However, the signAndCombineEcdsa function allows you to combine signature shares directly within a Lit Action, which is useful for when you want to make use of the signed data within your Lit Action e.g. submitting a signed transaction. The signature shares will remain within the confines of each Lit node's Trusted Execution Environment (TEE) without ever being exposed to the outside world.

When you call the signAndCombineEcdsa function, signature shares are collected from each Lit node before being combined on a single node. The following example demonstrates how you can use this functionality to sign a blockchain transaction using ethers.js

Prerequisites

Complete Code Example

The complete code example is available in the Lit Developer Guides Code Repository. There you can find a Node.js implementation of the code.

Example Lit Action

The following Lit Action uses signAndCombineEcdsa to combine partial signatures provided by each Lit node, each of which signs a share of the toSign variable — this variable contains the hash of the serialized transaction. After combining these shares into a complete signature, we use ethers.js to serialize the transaction again, this time including the signature, to finalize it for submission.

const _litActionCode = async () =>  {
const signature = await Lit.Actions.signAndCombineEcdsa({
toSign,
publicKey,
sigName,
});

const jsonSignature = JSON.parse(signature);
jsonSignature.r = "0x" + jsonSignature.r.substring(2);
jsonSignature.s = "0x" + jsonSignature.s;
const hexSignature = ethers.utils.joinSignature(jsonSignature);

const signedTx = ethers.utils.serializeTransaction(
unsignedTransaction,
hexSignature
);

const recoveredAddress = ethers.utils.recoverAddress(toSign, hexSignature);
console.log("Recovered Address:", recoveredAddress);

const response = await Lit.Actions.runOnce(
{ waitForResponse: true, name: "txnSender" },
async () => {
try {
const rpcUrl = await Lit.Actions.getRpcUrl({ chain });
const provider = new ethers.providers.JsonRpcProvider(rpcUrl);
const transactionReceipt = await provider.sendTransaction(signedTx);

return `Transaction Sent Successfully. Transaction Hash: ${transactionReceipt.hash}`;
} catch (error) {
return `Error: When sending transaction: ${error.message}`;
}
}
);

Lit.Actions.setResponse({ response });
};

const litActionCode = `(${_litActionCode.toString()})();`;

Summary

This guide demonstrates how to combine PKP signature shares, and submit a signed transaction all within a Lit Action.

If you'd like to learn more about Lit Actions, check out the Lit Actions SDK, or our Advanced Topics section on Lit Actions.

info

Not finding the answer you're looking for? Share your feedback on these docs by creating an issue in our GitHub Issues and Reports repository or get support by visiting our Support page.