Skip to content

Commit

Permalink
silent-sdk
Browse files Browse the repository at this point in the history
  • Loading branch information
21fahm committed Sep 17, 2024
1 parent 7f87489 commit ec22e21
Show file tree
Hide file tree
Showing 3 changed files with 224 additions and 10 deletions.
25 changes: 15 additions & 10 deletions content/docs/silent/integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
title: Bitcoin Silent Payments Integration
type: docs
prev: docs/silent
next: docs/private
next: docs/private/sdk
---

> Special credit to [_cake wallet_](https://github.com/cake-tech/bitcoin_base/tree/cake-update-v5 "cake wallet").
{{< callout type="info" >}}
This is a Dart package, and we are working on a JavaScript SDK for broader adoption.
This is a Dart package. To use an SDK go [here](./../sdk).
{{< /callout >}}

## @shakesco/bitcoin_base
Expand Down Expand Up @@ -37,7 +37,11 @@ You can generate a silent payment address in three ways:

##### Private Keys

If you are not a wallet provider, use this method. More specifically, you can make the user sign a message and then derive `b_scan` and `b_spend` from the resulting [signature]()(Use `r` as `b_scan` and `s` as `b_spend` or vice versa).
If you are not a wallet provider, use this method. More specifically, you can make the user sign a message and then derive `b_scan` and `b_spend` from the resulting [signature](https://cryptobook.nakov.com/digital-signatures/ecdsa-sign-verify-messages#ecdsa-sign) (Use `r` as `b_scan` and `s` as `b_spend` or vice versa).

{{< callout type="warning" >}}
If you are not using this method, ensure that a cryptographically secure random number generator is being used.
{{< /callout >}}

```dart {filename="index.dart"}
void main() {
Expand All @@ -52,13 +56,13 @@ void main() {
}
```

##### Mnemoni and HD Key
##### Mnemonic and HD Key

If you are a wallet provider, use this method.

```dart {filename="index.dart"}
void main() {
final mnemonic = "";
final mnemonic = ""; // 12, 15, 24 word phrase
final paymentOwner = bitcoin_base.SilentPaymentOwner.fromMnemonic(mnemonic);
print(paymentOwner.toAddress());
Expand Down Expand Up @@ -93,7 +97,8 @@ void main() {
]).createOutputs([
bitcoin_base.ECPrivateInfo(
bitcoin_base.ECPrivate.fromHex(sender_privateKey),
false)
false // If the output is from a taproot address
)
], [
bitcoin_base.SilentPaymentDestination(
amount: amount,
Expand All @@ -116,6 +121,8 @@ Scanning for funds is a drawback of silent payments. So below is how you can che
2. Public key outputted.
3. Script and amount from the outputted taproot address

For more info, go [here](https://github.com/bitcoin/bips/blob/master/bip-0352.mediawiki#scanning-silent-payment-eligible-transactions)

```dart {filename="index.dart"}
void main() {
final tx_hash = "";
Expand Down Expand Up @@ -184,7 +191,5 @@ Thats it! 🎊🎊🎊

If you love what we do to progress privacy, [contribute](https://me-qr.com/text/vPod5qN0 "btc_addr") to further development

<img
src="/images/bitcoin_address.png"
alt="btc_addr" width="300"
height="200">
<img src="/images/bitcoin_address.png" alt="btc_addr" style="display: inline-block; margin-right: 100px; margin-left: 70px;" width="200" height="200">
<img src="/images/silent.png" alt="btc_addr" width="200" style="display: inline-block; margin-right: 10px;" height="200">
209 changes: 209 additions & 0 deletions content/docs/silent/sdk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
---
title: SDK
type: docs
prev: docs/silent/integration
next: docs/private
---

## @shakesco/silent

### Install

To get started, install the package with your package manager.

```shell {filename=cmd}
npm i @shakesco/silent
```

After installing:

```js {filename="index.js"}
const shakesco = require("@shakesco/silent");
const {
KeyGeneration,
SilentPaymentDestination,
SilentPaymentBuilder,
ECPrivateInfo,
Network,
BitcoinScriptOutput,
bip32,
bip39
} = shakesco;
```

### Generate Silent Payment address

This will generate the silent payment address. It prepares a receiver to receive silent payments.
You can generate a silent payment address in three ways:

##### Private Keys

If you are not a wallet provider, use this method. More specifically, you can make the user sign a message and then derive `b_scan` and `b_spend` from the resulting [signature](https://cryptobook.nakov.com/digital-signatures/ecdsa-sign-verify-messages#ecdsa-sign) (Use `r` as `b_scan` and `s` as `b_spend` or vice versa).

{{< callout type="warning" >}}
If you are not using this method, ensure that a cryptographically secure random number generator is being used.
{{< /callout >}}

```js {filename="index.js"}
function main() {
const b_scan = "";
const b_spend = "";
const keys = KeyGeneration.fromPrivateKeys({
b_scan: b_scan,
b_spend: b_spend,
network: "testnet",
});
const silentPaymentAddress = keys.toAddress();
console.log(silentPaymentAddress); // Silent payment address
}
```

##### Mnemonic and HD Key

If you are a wallet provider, use this method.

```js {filename="index.js"}
function main() {
const mnemonic = ""; // 12, 15, 24 word phrase
const keys = KeyGeneration.fromMnemonic(mnemonic);
const silentPaymentAddress = keys.toAddress();
console.log(silentPaymentAddress);

// const seed = bip39.mnemonicToSeedSync(mnemonic);
// const node = bip32.fromSeed(seed);
// const keys = KeyGeneration.fromHd(node);
// const silentPaymentAddress = keys.toAddress();
// console.log(silentPaymentAddress);
}
```

### Create a taproot address destination

Here is where you create a destination address for the user to send to a newly generated Taproot address, derived from the receiver's silent payment address generated above.
You will need:

1. The Unspent Transaction Output(UTXO) of the user, hash and output_index.
2. The private key of the UTXO in 1 above.
3. Amount the user wants to send. Should be in satoshis(1 BTC = 100<sup>6</sup> satoshis)
4. Finally, the public keys of the 2 secret shares, `B_scan` and `B_spend`

```js {filename="index.js"}
function main() {
const addressPubKeys = KeyGeneration.fromAddress(silentPaymentAddress);
const vinOutpoints = [
{
txid: "367e24cac43a7d77621ceb1cbc1cf4a7719fc81b05b07b38f99b043f4e8b95dc",
index: 1,
},
];

const pubkeys = [
"025c471f0e7d30d6f9095058bbaedaf13e1de67dbfcbe8328e6378d2a3bfb5cfd0",
];
const UTXOPrivatekey = "";
const builder = new SilentPaymentBuilder({
vinOutpoints: vinOutpoints,
pubkeys: pubkeys,
}).createOutputs(
[
new ECPrivateInfo(
UTXOPrivatekey,
false // If the output is from a taproot address
),
],
[
new SilentPaymentDestination({
amount: 1000,
network: Network.Testnet,
version: 0,
scanPubkey: addressPubKeys.B_scan,
spendPubkey: addressPubKeys.B_spend,
}),
]
);
console.log(builder[silentPaymentAddress][0]); // Access the taproot address and send 1000 satoshis
}
```

### Scan for funds

Scanning for funds is a drawback of silent payments. So below is how you can check if a certain transaction belongs to a user. You will need:

1. The transaction input's tx_hash and output_index.
2. Public key outputted.
3. Script and amount from the outputted taproot address

For more info, go [here](https://github.com/bitcoin/bips/blob/master/bip-0352.mediawiki#scanning-silent-payment-eligible-transactions)

```js {filename="index.js"}
function main() {
const vinOutpoints = [
{
txid: "367e24cac43a7d77621ceb1cbc1cf4a7719fc81b05b07b38f99b043f4e8b95dc",
index: 1,
},
];

const pubkeys = [
"025c471f0e7d30d6f9095058bbaedaf13e1de67dbfcbe8328e6378d2a3bfb5cfd0",
];
const search = new SilentPaymentBuilder({
vinOutpoints: vinOutpoints,
pubkeys: pubkeys,
network: Network.Testnet,
}).scanOutputs(keys.b_scan, keys.B_spend, [
new BitcoinScriptOutput(
"5120fdcb28bcea339a5d36d0c00a3e110b837bf1151be9e7ac9a8544e18b2f63307d",
BigInt(1000)
),
]);

console.log(
search[builder[keys.toAddress()][0].address.pubkey.toString("hex")].output
);
}
```

If the address above matches the taproot address from the output in the transaction, it belongs to the user.

### Spend funds

If the funds belong to the user, they can spend like so:

First, you will need:

1. The transaction input's tx_hash and output_index.
2. Public key outputted.
3. Receiver's spend and scan private keys.

```js {filename="index.js"}
function main() {
const vinOutpoints = [
{
txid: "367e24cac43a7d77621ceb1cbc1cf4a7719fc81b05b07b38f99b043f4e8b95dc",
index: 1,
},
];

const pubkeys = [
"025c471f0e7d30d6f9095058bbaedaf13e1de67dbfcbe8328e6378d2a3bfb5cfd0",
];
const private_key = new SilentPaymentBuilder({
vinOutpoints: vinOutpoints,
pubkeys: pubkeys,
}).spendOutputs(keys.b_scan, keys.b_spend);

console.log(private_key); // use this to build a taproot transaction with bitcoinjs: https://github.com/bitcoinjs/bitcoinjs-lib
}
```

The receiver can use `private_key` to spend the funds!

Thats it! 🎊🎊🎊

### Contribute

If you love what we do to progress privacy, [contribute](https://me-qr.com/text/vPod5qN0 "btc_addr") to further development

<img src="/images/bitcoin_address.png" alt="btc_addr" style="display: inline-block; margin-right: 100px; margin-left: 70px;" width="200" height="200">
<img src="/images/silent.png" alt="btc_addr" width="200" style="display: inline-block; margin-right: 10px;" height="200">
Binary file added static/images/silent.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit ec22e21

Please sign in to comment.