{"id":20383481,"url":"https://github.com/shakesco/shakesco-private","last_synced_at":"2026-01-22T18:05:24.191Z","repository":{"id":245073366,"uuid":"714807273","full_name":"shakesco/shakesco-private","owner":"shakesco","description":"Ethereum Stealth Addresses","archived":false,"fork":false,"pushed_at":"2025-09-09T14:36:01.000Z","size":48,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-09T17:37:17.003Z","etag":null,"topics":["ethereum","polygon","privacy","private","shakesco","stealth-addresses"],"latest_commit_sha":null,"homepage":"https://shakesco.com","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shakesco.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-11-05T21:29:10.000Z","updated_at":"2025-09-09T14:36:05.000Z","dependencies_parsed_at":"2024-06-19T15:48:14.021Z","dependency_job_id":"2c1a5577-6a08-4cbd-bfdb-fbc72d187258","html_url":"https://github.com/shakesco/shakesco-private","commit_stats":null,"previous_names":["shakesco/shakesco-private"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/shakesco/shakesco-private","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shakesco%2Fshakesco-private","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shakesco%2Fshakesco-private/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shakesco%2Fshakesco-private/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shakesco%2Fshakesco-private/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shakesco","download_url":"https://codeload.github.com/shakesco/shakesco-private/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shakesco%2Fshakesco-private/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28667881,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-22T17:07:18.858Z","status":"ssl_error","status_checked_at":"2026-01-22T17:05:02.040Z","response_time":144,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ethereum","polygon","privacy","private","shakesco","stealth-addresses"],"created_at":"2024-11-15T02:22:51.435Z","updated_at":"2026-01-22T18:05:24.178Z","avatar_url":"https://github.com/shakesco.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Shakesco Stealth Addresses\n\n\u003e Special credit to [_umbra-cash_](https://app.umbra.cash/ \"Umbra\").\n\nThis package will allow you to perform private transactions where only the sender and receiver\nknow the destination of the transaction. To understand how it works: [**umbra-docs**](https://app.umbra.cash/faq#how-does-it-work-technical \"Umbra\"), [**EIP 5564**](https://eips.ethereum.org/EIPS/eip-5564 \"EIP 5564\")\n\n_We assume that you have a single private key securing your wallet and that you are signing the same message hash. The former is not advised._\n\nTo get started:\n\n```shell\nnpm i @shakesco/private\n```\n\nAfter installing:\n\n```javascript\nconst shakesco = require(\"@shakesco/private\");\nconst { KeyPair, RandomNumber, StealthKeyRegistry, utils } = shakesco;\nconst { IsUsersFunds, generateKeyPair, prepareSend } = shakesco;\n```\n\nWe use the umbra registry to register stealth keys. To check if user has keys:\n\n```javascript\nconst provider = new ethers.JsonRpcProvider(process.env.RPC_URL);\nconst registry = new StealthKeyRegistry(provider);\n\nconst { spendingPublicKey, viewingPublicKey } = await registry.getStealthKeys(\n  recipientId\n);\nconsole.log(spendingPublicKey);\nconsole.log(viewingPublicKey);\n```\n\nIf an empty string is returned the user has not registered for private transactions. So you register them as follows:\n\n1. If you want to set keys for a smart wallet:\n\n```javascript\nconst provider = new ethers.JsonRpcProvider(process.env.RPC_URL);\nconst signer = new ethers.Wallet(process.env.PRIV_KEY, provider);\nconst signature = await signer.signMessage(messageHash);\nconst { spendingKeyPair, viewingKeyPair } = await generateKeyPair(signature);\nconsole.log(viewingKeyPair.privateKeyHex); // storing this for the user is okay! To fetch transactions for them easily. You can also choose to not store it.\nconst registry = new StealthKeyRegistry(provider);\n\nconst { spendingPrefix, spendingPubKeyX, viewingPrefix, viewingPubKeyX } =\n  await registry.setSmartStealthKeys(\n    spendingKeyPair.publicKeyHex,\n    viewingKeyPair.publicKeyHex\n  );\n```\n\n\u003e You can call the registry contract with the above details as the parameter.\n\n2. If you want to set keys for EOAs:\n\n```javascript\nconst provider = new ethers.JsonRpcProvider(process.env.RPC_URL);\nconst { spendingKeyPair, viewingKeyPair } = await generateKeyPair(setupSig);\nconst registry = new StealthKeyRegistry(provider);\n\nconst { spendingPrefix, spendingPubKeyX, viewingPrefix, viewingPubKeyX } =\n  await registry.SetEOAStealthKeys(\n    spendingKeyPair.publicKeyHex,\n    viewingKeyPair.publicKeyHex\n  );\n```\n\nYour user is now ready to perform private transactions. To prepare the payee to receive a private transaction:\n\n```javascript\n   const payee = //payee address\n   const provider = //node provider eg: alchemy\n   const { stealthKeyPair, pubKeyXCoordinate, encrypted } =\n        await prepareSend(address, provider);\n   console.log(stealthKeyPair.address);// address funds should be sent to. This is a stealth address that the payee can control.\n   console.log(pubKeyXCoordinate); // Public key that the payee will use to decrypt the ciphertext hence proving funds belong to them\n   console.log(encrypted.ciphertext);// Encrypted random number used to generate the stealth address.\n```\n\n\u003e NOTE📓: You need to send the ciphertext and publickey to the payee. Otherwise they will not be able to prove ownership of funds. You can use tools like [**the graph**](https://thegraph.com/en/ \"Graph\") or [**moralis**](https://moralis.io/ \"Moralis\") to query the 'Announcement' from your private contract after a transaction has been initiated.\n\n```solidity\n  event Announcement (\n      uint256 indexed schemeId,\n      address indexed stealthAddress,\n      address indexed caller,\n      bytes ephemeralPubKey,\n      bytes metadata\n    );\n```\n\nTo check if funds belong to a certain user:\n\n```javascript\nIsUsersFunds(object.announcements[i], provider, secret, sender).then((data) =\u003e {\n  if (data.isForUser) {\n    //belongs to user\n    //perform any action you want with the data.\n  }\n});\n```\n\nIf the funds belong to the user they can spend the funds. To create the private key that will be able to do this:\n\n```javascript\nconst provider = new ethers.JsonRpcProvider(process.env.RPC_URL);\nconst signer = new ethers.Wallet(process.env.PRIV_KEY, provider);\nconst signature = await signer.signMessage(messageHash);\nconst { spendingKeyPair, viewingKeyPair } = await generateKeyPair(signature);\n\nconst payload = {\n  ephemeralPublicKey: uncompressedPubKey,\n  ciphertext: ciphertext,\n};\n\nconst random = await viewkey.decrypt(payload);\n\nconst privkey = KeyPair.computeStealthPrivateKey(\n  spendingKeyPair.privateKeyHex,\n  random //decrypted random number\n);\n\nconst wallet = new ethers.Wallet(privkey, provider);\nconst txResponse = await wallet.sendTransaction({\n  value: ethers.parseEther(value),\n  to: address,\n});\nconst response = await txResponse.wait();\n```\n\nYou have successfully sent a private transactions. We aim to help umbra expand the adoption of stealth payments. ZK will improve upon stealth addresses ensuring Ethereum is more private!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshakesco%2Fshakesco-private","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshakesco%2Fshakesco-private","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshakesco%2Fshakesco-private/lists"}