@shakesco/private
v1.2.1
Published
Shakesco Stealth payments package
Downloads
29
Readme
@shakesco/private
JavaScript SDK for building privacy-preserving Ethereum transfers using stealth addresses.
Special credit to Umbra Cash for pioneering stealth payment infrastructure.
What It Does
The @shakesco/private SDK lets you implement truly private crypto transactions. No one except the sender and receiver can link the payment to the recipient's known address.
Learn more:
Installation
npm i @shakesco/privateQuick Start
const shakesco = require("@shakesco/private");
const { KeyPair, RandomNumber, StealthKeyRegistry, utils } = shakesco;
const { IsUsersFunds, generateKeyPair, prepareSend } = shakesco;Security Note: This implementation assumes a single private key secures your wallet and that you're signing the same message hash.
Basic Workflow
1. Check if User Has Stealth Keys
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
const registry = new StealthKeyRegistry(provider);
const { spendingPublicKey, viewingPublicKey } =
await registry.getStealthKeys(recipientId);
if (!spendingPublicKey) {
console.log("User needs to register stealth keys first");
}2. Register Stealth Keys
For Smart Wallets (ERC-4337):
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
const signer = new ethers.Wallet(process.env.PRIV_KEY, provider);
const signature = await signer.signMessage(messageHash);
const { spendingKeyPair, viewingKeyPair } = await generateKeyPair(signature);
const registry = new StealthKeyRegistry(provider);
const { spendingPrefix, spendingPubKeyX, viewingPrefix, viewingPubKeyX } =
await registry.setSmartStealthKeys(
spendingKeyPair.publicKeyHex,
viewingKeyPair.publicKeyHex
);
// Use these values to call the registry contract via your smart walletFor EOAs (Regular Wallets):
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
const { spendingKeyPair, viewingKeyPair } = await generateKeyPair(setupSig);
const registry = new StealthKeyRegistry(provider);
const { spendingPrefix, spendingPubKeyX, viewingPrefix, viewingPubKeyX } =
await registry.SetEOAStealthKeys(
spendingKeyPair.publicKeyHex,
viewingKeyPair.publicKeyHex
);3. Generate Stealth Address
const payee = "0x..."; // Recipient's address
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
const { stealthKeyPair, pubKeyXCoordinate, encrypted } = await prepareSend(
payee,
provider
);
console.log(stealthKeyPair.address); // Send funds HERE
console.log(pubKeyXCoordinate); // Share with recipient
console.log(encrypted.ciphertext); // Share with recipientImportant: You must share pubKeyXCoordinate and encrypted.ciphertext with the recipient so they can prove ownership and spend the funds.
4. Announce the Payment
Emit this event from your contract so recipients can discover their payments:
event Announcement(
address indexed receiver,
uint256 amount,
address indexed tokenAddress,
bytes32 pkx,
bytes32 ciphertext
);Use indexing services like The Graph or Moralis to help recipients scan for announcements efficiently.
5. Check if Funds Belong to User
IsUsersFunds(announcement, provider, viewingPrivateKey, sender).then((data) => {
if (data.isForUser) {
console.log("Amount:", data.amount);
console.log("Token:", data.tokenAddress);
console.log("Stealth address:", data.stealthAddress);
}
});6. Spend Private Funds
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
const signer = new ethers.Wallet(process.env.PRIV_KEY, provider);
const signature = await signer.signMessage(messageHash);
const { spendingKeyPair, viewingKeyPair } = await generateKeyPair(signature);
const payload = {
ephemeralPublicKey: uncompressedPubKey,
ciphertext: ciphertext,
};
const random = await viewingKeyPair.decrypt(payload);
const stealthPrivateKey = KeyPair.computeStealthPrivateKey(
spendingKeyPair.privateKeyHex,
random
);
const wallet = new ethers.Wallet(stealthPrivateKey, provider);
const txResponse = await wallet.sendTransaction({
value: ethers.parseEther(value),
to: destinationAddress,
});
await txResponse.wait();
console.log("Private funds successfully transferred!");Documentation
For complete integration guides and examples, visit: docs.shakesco.com/stealth-payments
About Stealth Addresses
What are spending and viewing keys?
- Spending Keys - Used to generate stealth addresses and spend from them
- Viewing Keys - Allow scanning for incoming transactions without spending ability
This separation means you can monitor for payments without risking your funds.
Note: Storing viewingKeyPair.privateKeyHex for users is acceptable - it only enables transaction scanning, not spending.
Resources
Future
While stealth addresses provide strong privacy today, zero-knowledge proofs will eventually offer even better solutions. Until then, stealth payments are the best way to bring privacy to Ethereum transactions.
We aim to help expand the adoption of stealth payments and make Ethereum more private!
