{"id":15148804,"url":"https://github.com/shakesco/shakesco-silent","last_synced_at":"2026-02-19T13:02:35.118Z","repository":{"id":257663068,"uuid":"858952909","full_name":"shakesco/shakesco-silent","owner":"shakesco","description":"Bitcoin Silent Payments","archived":false,"fork":false,"pushed_at":"2026-02-05T11:45:16.000Z","size":131,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-05T23:10:48.415Z","etag":null,"topics":["bitcoin","payments","privacy","silent-payments","stealth-payments"],"latest_commit_sha":null,"homepage":"https://docs.shakesco.com/docs/silent/","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":"2024-09-17T20:20:24.000Z","updated_at":"2026-02-05T11:45:20.000Z","dependencies_parsed_at":"2025-01-07T17:27:45.978Z","dependency_job_id":"ba94a6e2-a3a7-4746-abb7-f5d57f9897d7","html_url":"https://github.com/shakesco/shakesco-silent","commit_stats":{"total_commits":4,"total_committers":1,"mean_commits":4.0,"dds":0.0,"last_synced_commit":"049a89c9592c401a175c5a9b10bdc2d0760d1a1a"},"previous_names":["shakesco/shakesco-silent"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/shakesco/shakesco-silent","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shakesco%2Fshakesco-silent","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shakesco%2Fshakesco-silent/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shakesco%2Fshakesco-silent/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shakesco%2Fshakesco-silent/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shakesco","download_url":"https://codeload.github.com/shakesco/shakesco-silent/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shakesco%2Fshakesco-silent/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29614592,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-19T10:52:55.328Z","status":"ssl_error","status_checked_at":"2026-02-19T10:52:26.323Z","response_time":117,"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":["bitcoin","payments","privacy","silent-payments","stealth-payments"],"created_at":"2024-09-26T13:23:20.491Z","updated_at":"2026-02-19T13:02:35.101Z","avatar_url":"https://github.com/shakesco.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @shakesco/silent\n\nJavaScript SDK for receiving Bitcoin privately with silent payments (BIP-352).\n\n\u003e Special thanks to [Ruben Somsen](https://x.com/SomsenRuben) and [Josie Bake](https://x.com/josibake) for their groundbreaking work on BIP-352.\n\n## What It Does\n\nThe `@shakesco/silent` SDK lets you implement Bitcoin silent payments, allowing users to:\n\n- ✅ Share a single address for all payments\n- ✅ Receive Bitcoin privately\n- ✅ Maintain transaction unlinkability\n- ✅ Avoid notification transaction fees\n\n**Learn more:**\n\n- [BIP-352 Specification](https://github.com/bitcoin/bips/blob/master/bip-0352.mediawiki)\n- [Silent Payments Explained](https://silentpayments.xyz/docs/explained/)\n- [Full documentation](https://docs.shakesco.com/silent-payments/)\n\n## Installation\n\n```bash\nnpm i @shakesco/silent\n```\n\n## Quick Start\n\n```javascript\nconst shakesco = require(\"@shakesco/silent\");\nconst {\n  KeyGeneration,\n  SilentPaymentDestination,\n  SilentPaymentBuilder,\n  ECPrivateInfo,\n  Network,\n  BitcoinScriptOutput,\n  bip32,\n  bip39,\n} = shakesco;\n```\n\n## Integration Workflow\n\n1. Generate silent payment address\n2. Create destination address for each payment\n3. Scan for incoming funds\n4. Spend received funds\n\n---\n\n## 1. Generate Silent Payment Address\n\n### From Private Keys (Recommended for Apps)\n\n**Best for:** Non-wallet applications where users control their keys\n\n```javascript\nconst b_scan = \"\"; // Scan private key\nconst b_spend = \"\"; // Spend private key\n\nconst keys = KeyGeneration.fromPrivateKeys({\n  b_scan: b_scan,\n  b_spend: b_spend,\n  network: \"testnet\",\n});\n\nconst silentPaymentAddress = keys.toAddress();\nconsole.log(silentPaymentAddress);\n```\n\n**Pro tip:** Make users sign a message, then derive `b_scan` and `b_spend` from the [ECDSA signature](https://cryptobook.nakov.com/digital-signatures/ecdsa-sign-verify-messages#ecdsa-sign):\n\n- Use `r` as `b_scan`\n- Use `s` as `b_spend` (or vice versa)\n\nThis ensures cryptographically secure randomness without storing additional keys.\n\n### From Mnemonic (For Wallets)\n\n**Best for:** Wallet providers managing user funds\n\n```javascript\nconst mnemonic = \"\"; // 12, 15, or 24 word phrase\nconst keys = KeyGeneration.fromMnemonic(mnemonic);\nconst silentPaymentAddress = keys.toAddress();\nconsole.log(silentPaymentAddress);\n```\n\n**Alternative using HD key:**\n\n```javascript\nconst seed = bip39.mnemonicToSeedSync(mnemonic);\nconst node = bip32.fromSeed(seed);\nconst keys = KeyGeneration.fromHd(node);\nconst silentPaymentAddress = keys.toAddress();\n```\n\n**Security Note:** If not using the signature-derived method, ensure you're using a cryptographically secure random number generator.\n\n### Create a Change Address\n\n**Critical for privacy:** Never send change to a public address after making silent payments.\n\n```javascript\nconst keys = KeyGeneration.fromPrivateKeys({\n  b_scan: b_scan,\n  b_spend: b_spend,\n  network: \"testnet\",\n});\n\n// Always use label 0 for change (per BIP-352 spec)\nconst changeSilentPaymentAddress = keys.toLabeledSilentPaymentAddress(0);\nconsole.log(changeSilentPaymentAddress.toAddress());\n```\n\n**Why this matters:** If you send 10 silent payments to friends, then send change to your public address, you've exposed:\n\n- ❌ Your own private transaction history\n- ❌ Your friends' payment patterns\n- ❌ Links between all 10 transactions\n\n**Solution:** Always use a labeled silent payment address for change.\n\nReference: [BIP-352 Labels for Change](https://github.com/bitcoin/bips/blob/master/bip-0352.mediawiki#labels_for_change)\n\n---\n\n## 2. Create Destination Address\n\nGenerate a unique taproot address for the payment:\n\n```javascript\n// Parse recipient's silent payment address\nconst addressPubKeys = KeyGeneration.fromAddress(silentPaymentAddress);\n\n// Your UTXO details\nconst vinOutpoints = [\n  {\n    txid: \"367e24cac43a7d77621ceb1cbc1cf4a7719fc81b05b07b38f99b043f4e8b95dc\",\n    index: 1,\n  },\n];\n\nconst pubkeys = [\n  \"025c471f0e7d30d6f9095058bbaedaf13e1de67dbfcbe8328e6378d2a3bfb5cfd0\",\n];\n\nconst UTXOPrivatekey = \"\"; // Your UTXO private key\n\n// Build the destination\nconst builder = new SilentPaymentBuilder({\n  vinOutpoints: vinOutpoints,\n  pubkeys: pubkeys,\n}).createOutputs(\n  [\n    new ECPrivateInfo(\n      UTXOPrivatekey,\n      false // Set true if output is from taproot\n    ),\n  ],\n  [\n    new SilentPaymentDestination({\n      amount: 1000, // Satoshis (1 BTC = 100,000,000 sats)\n      network: Network.Testnet,\n      version: 0,\n      scanPubkey: addressPubKeys.B_scan,\n      spendPubkey: addressPubKeys.B_spend,\n    }),\n  ]\n);\n\n// Get the destination taproot address\nconst destinationAddress = builder[silentPaymentAddress][0];\nconsole.log(\"Send 1000 sats to:\", destinationAddress);\n```\n\n**What you need:**\n\n- UTXO transaction ID and output index\n- UTXO private key\n- Amount in satoshis\n- Recipient's scan and spend public keys (`B_scan`, `B_spend`)\n\n---\n\n## 3. Scan for Incoming Funds\n\n**Trade-off:** This is the main drawback of silent payments - you must scan the blockchain to detect incoming transactions.\n\n```javascript\nconst vinOutpoints = [\n  {\n    txid: \"367e24cac43a7d77621ceb1cbc1cf4a7719fc81b05b07b38f99b043f4e8b95dc\",\n    index: 1,\n  },\n];\n\nconst pubkeys = [\n  \"025c471f0e7d30d6f9095058bbaedaf13e1de67dbfcbe8328e6378d2a3bfb5cfd0\",\n];\n\nconst search = new SilentPaymentBuilder({\n  vinOutpoints: vinOutpoints,\n  pubkeys: pubkeys,\n  network: Network.Testnet,\n}).scanOutputs(\n  keys.b_scan, // Your scan private key\n  keys.B_spend, // Your spend public key\n  [\n    new BitcoinScriptOutput(\n      \"5120fdcb28bcea339a5d36d0c00a3e110b837bf1151be9e7ac9a8544e18b2f63307d\",\n      BigInt(1000)\n    ),\n  ]\n);\n\nconst foundOutput =\n  search[builder[keys.toAddress()][0].address.pubkey.toString(\"hex\")].output;\nconsole.log(foundOutput);\n```\n\nIf the output matches the taproot address → it's yours! 🎉\n\n**What you need for scanning:**\n\n- Transaction input's `txid` and `output_index`\n- Public key from the output\n- Script and amount from the taproot address\n\nLearn more: [BIP-352 Scanning](https://github.com/bitcoin/bips/blob/master/bip-0352.mediawiki#scanning-silent-payment-eligible-transactions)\n\n---\n\n## 4. Spend the Funds\n\nOnce you've confirmed funds belong to you, derive the private key:\n\n```javascript\nconst vinOutpoints = [\n  {\n    txid: \"367e24cac43a7d77621ceb1cbc1cf4a7719fc81b05b07b38f99b043f4e8b95dc\",\n    index: 1,\n  },\n];\n\nconst pubkeys = [\n  \"025c471f0e7d30d6f9095058bbaedaf13e1de67dbfcbe8328e6378d2a3bfb5cfd0\",\n];\n\nconst private_key = new SilentPaymentBuilder({\n  vinOutpoints: vinOutpoints,\n  pubkeys: pubkeys,\n}).spendOutputs(keys.b_scan, keys.b_spend);\n\nconsole.log(\"Private key:\", private_key);\n```\n\n**Tip:** Use this private key with [bitcoinjs-lib](https://github.com/bitcoinjs/bitcoinjs-lib) to build and sign your taproot transaction.\n\n---\n\n## That's It!\n\nYou've successfully implemented Bitcoin silent payments. Your users can now receive Bitcoin privately without address reuse.\n\n## Documentation\n\nFor complete integration guides and examples, visit: [docs.shakesco.com/silent-payments](https://docs.shakesco.com/silent-payments/)\n\n## Resources\n\n- [BIP-352 Specification](https://github.com/bitcoin/bips/blob/master/bip-0352.mediawiki) - Complete technical specification\n- [bitcoinjs-lib](https://github.com/bitcoinjs/bitcoinjs-lib) - Build Bitcoin transactions in JavaScript\n- [Silent Payments Explained](https://silentpayments.xyz/docs/explained/) - Protocol deep dive\n- [ECDSA Signatures](https://cryptobook.nakov.com/digital-signatures/ecdsa-sign-verify-messages) - Learn about signature-based key derivation\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshakesco%2Fshakesco-silent","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshakesco%2Fshakesco-silent","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshakesco%2Fshakesco-silent/lists"}