Skip to content

Commit

Permalink
Make imports in chain.md invisible (#1213)
Browse files Browse the repository at this point in the history
* Make imports in chain.md invisible

* Hide imports in wallet.md

* Make all core module md files imports hidden

* Cleanup imports on rpc markdown docs

* Try and figure weird travis behavior

* Get rid of uneeded nest qualifiers on mdoc
  • Loading branch information
Christewart committed Mar 10, 2020
1 parent d9881dd commit 89f1db6
Show file tree
Hide file tree
Showing 11 changed files with 114 additions and 78 deletions.
7 changes: 4 additions & 3 deletions .travis.yml
Expand Up @@ -48,9 +48,10 @@ matrix:
# compile website, to check for documentation regressions
- stage: test
name: Compile website and check formatting
script:
- sbt docs/mdoc
- sbt test:scalafmtCheck
env:
- TEST_COMMAND="test:scalafmtCheck docs/mdoc"
scala:
- 2.13.1

# Release snapshots/versions of all libraries
# run ci-release only if previous stages passed
Expand Down
17 changes: 8 additions & 9 deletions docs/applications/chain.md
Expand Up @@ -16,25 +16,28 @@ we demonstrate how to do this, while persisting it to disk. We should be
able to read this chain on subsequent runs, assuming we are connected
to the same `bitcoind` instance.

```scala mdoc:compile-only
```scala mdoc:invisible
import org.bitcoins.chain.blockchain._
import org.bitcoins.chain.blockchain.sync._
import org.bitcoins.chain.models._

import org.bitcoins.chain.config.ChainAppConfig
import org.bitcoins.rpc.config.BitcoindInstance
import org.bitcoins.rpc.client.common.BitcoindRpcClient
import org.bitcoins.rpc.client.common._
import org.bitcoins.testkit.chain._

import scala.concurrent._
import java.nio.file.Files
```

```scala mdoc:compile-only

implicit val ec = ExecutionContext.global

// We are assuming that a `bitcoind` regtest node is running the background.
// You can see our `bitcoind` guides to see how to connect
// to a local or remote `bitcoind` node.

import org.bitcoins.rpc.config.BitcoindInstance
import org.bitcoins.rpc.client.common.BitcoindRpcClient

val bitcoindInstance = BitcoindInstance.fromDatadir()
val rpcCli = BitcoindRpcClient(bitcoindInstance)

Expand All @@ -44,9 +47,7 @@ val getBestBlockHash = ChainTestUtil.bestBlockHashFnRpc(Future.successful(rpcCli

val getBlockHeader = ChainTestUtil.getBlockHeaderFnRpc(Future.successful(rpcCli))


// set a data directory
import java.nio.file.Files
val datadir = Files.createTempDirectory("bitcoin-s-test")

// set the currenet network to regtest
Expand All @@ -59,7 +60,6 @@ val config = ConfigFactory.parseString {
|""".stripMargin
}

import org.bitcoins.chain.config.ChainAppConfig
implicit val chainConfig = ChainAppConfig(datadir, config)

// Initialize the needed database tables if they don't exist:
Expand All @@ -77,7 +77,6 @@ val syncedChainApiF = for {
synced <- ChainSync.sync(handler, getBlockHeader, getBestBlockHash)
} yield synced


val syncResultF = syncedChainApiF.flatMap { chainApi =>
chainApi.getBlockCount.map(count => println(s"chain api blockcount=${count}"))

Expand Down
54 changes: 30 additions & 24 deletions docs/applications/wallet.md
Expand Up @@ -40,10 +40,36 @@ UTXOs with popular database like Postgres, SQLite, etc.
This code snippet you have a running `bitcoind` instance, locally
on regtest.

```scala mdoc:invisible

import org.bitcoins.chain.blockchain.ChainHandler
import org.bitcoins.chain.blockchain.sync.ChainSync
import org.bitcoins.chain.config.ChainAppConfig
import org.bitcoins.chain.api.ChainApi
import org.bitcoins.chain.models._

import org.bitcoins.core.api._
import ChainQueryApi._
import org.bitcoins.core.crypto._
import org.bitcoins.core.protocol._
import org.bitcoins.core.protocol.transaction._
import org.bitcoins.core.currency._
import org.bitcoins.keymanager.bip39._
import org.bitcoins.rpc.client.common.BitcoindRpcClient
import org.bitcoins.rpc.config.BitcoindInstance
import org.bitcoins.wallet.config.WalletAppConfig
import org.bitcoins.wallet.api.LockedWalletApi
import org.bitcoins.wallet.Wallet

import com.typesafe.config.ConfigFactory
import java.nio.file.Files
import scala.concurrent._
```

```scala mdoc:compile-only
implicit val ec = scala.concurrent.ExecutionContext.global

import com.typesafe.config.ConfigFactory

val config = ConfigFactory.parseString {
"""
| bitcoin-s {
Expand All @@ -52,49 +78,41 @@ val config = ConfigFactory.parseString {
""".stripMargin
}

import java.nio.file.Files

val datadir = Files.createTempDirectory("bitcoin-s-wallet")

import org.bitcoins.wallet.config.WalletAppConfig

implicit val walletConfig = WalletAppConfig(datadir, config)

// we also need to store chain state for syncing purposes
import org.bitcoins.chain.config.ChainAppConfig
implicit val chainConfig = ChainAppConfig(datadir, config)

// when this future completes, we have
// created the necessary directories and
// databases for managing both chain state
// and wallet state
import scala.concurrent._
val configF: Future[Unit] = for {
_ <- walletConfig.initialize()
_ <- chainConfig.initialize()
} yield ()

import org.bitcoins.rpc.config.BitcoindInstance
val bitcoindInstance = BitcoindInstance.fromDatadir()

import org.bitcoins.rpc.client.common.BitcoindRpcClient
val bitcoind = BitcoindRpcClient(bitcoindInstance)

// when this future completes, we have
// synced our chain handler to our bitcoind
// peer
import org.bitcoins.chain.api.ChainApi
val syncF: Future[ChainApi] = configF.flatMap { _ =>
val getBestBlockHashFunc = { () =>
bitcoind.getBestBlockHash
}

import org.bitcoins.core.crypto.DoubleSha256DigestBE

val getBlockHeaderFunc = { hash: DoubleSha256DigestBE =>
bitcoind.getBlockHeader(hash).map(_.blockHeader)
}


import org.bitcoins.chain.models._
import org.bitcoins.chain.blockchain.ChainHandler
val blockHeaderDAO = BlockHeaderDAO()
val compactFilterHeaderDAO = CompactFilterHeaderDAO()
val compactFilterDAO = CompactFilterDAO()
Expand All @@ -105,12 +123,10 @@ val syncF: Future[ChainApi] = configF.flatMap { _ =>
blockchains = Vector.empty,
blockFilterCheckpoints = Map.empty)

import org.bitcoins.chain.blockchain.sync.ChainSync
ChainSync.sync(chainHandler, getBlockHeaderFunc, getBestBlockHashFunc)
}

//initialize our key manager, where we store our keys
import org.bitcoins.keymanager.bip39._
//you can add a password here if you want
//val bip39PasswordOpt = Some("my-password-here")
val bip39PasswordOpt = None
Expand All @@ -120,16 +136,9 @@ val keyManager = BIP39KeyManager.initialize(walletConfig.kmParams, bip39Password

// once this future completes, we have a initialized
// wallet

import org.bitcoins.wallet.api.LockedWalletApi
import org.bitcoins.wallet.Wallet
import org.bitcoins.core.api._
import org.bitcoins.core.crypto._
import org.bitcoins.core.protocol._
val wallet = Wallet(keyManager, new NodeApi {
override def downloadBlocks(blockHashes: Vector[DoubleSha256Digest]): Future[Unit] = Future.successful(())
}, new ChainQueryApi {
import org.bitcoins.core.api.ChainQueryApi._
override def getBlockHeight(blockHash: DoubleSha256DigestBE): Future[Option[Int]] = Future.successful(None)
override def getBestBlockHash(): Future[DoubleSha256DigestBE] = Future.successful(DoubleSha256DigestBE.empty)
override def getNumberOfConfirmations(blockHashOpt: DoubleSha256DigestBE): Future[Option[Int]] = Future.successful(None)
Expand All @@ -143,9 +152,6 @@ val walletF: Future[LockedWalletApi] = configF.flatMap { _ =>

// when this future completes, ww have sent a transaction
// from bitcoind to the Bitcoin-S wallet
import org.bitcoins.core.crypto._
import org.bitcoins.core.protocol.transaction._
import org.bitcoins.core.currency._
val transactionF: Future[(Transaction, Option[DoubleSha256DigestBE])] = for {
wallet <- walletF
address <- wallet.getNewAddress()
Expand Down
17 changes: 9 additions & 8 deletions docs/core/addresses.md
Expand Up @@ -20,18 +20,17 @@ you can generate bech32 addresses in four(!) lines of code
(not counting comments and imports), so now there's no
reason to keep using legacy transaction formats.

```scala mdoc:to-string
```scala mdoc:invisible
import org.bitcoins.core.{crypto, protocol, config}
// if you want to get addresses for mainnet, just import
// config.MainNet here instead
import config.TestNet3
import crypto.ECPrivateKey

// this gets all addresses into scope
import protocol._

// this gets all scriptPubKeys into scope
import protocol.script._
import org.bitcoins.core.protocol.P2PKHAddress
```

```scala mdoc:to-string

// this generates a random private key
val privkey = ECPrivateKey()
Expand All @@ -44,6 +43,8 @@ val segwitAddress = {
val scriptPubKey = P2WPKHWitnessSPKV0(pubkey)
Bech32Address(scriptPubKey, TestNet3)
}

println(segwitAddress.toString)
```

## Generating legacy (base58) addresses
Expand All @@ -53,10 +54,10 @@ compatability reasons, that's also a walk in the park.
Take a look:

```scala mdoc:to-string
// pay-to-pubkey-hash address
import org.bitcoins.core.protocol.P2PKHAddress

// we're reusing the same private/public key pair
// from before. don't do this in an actual application!
val legacyAddress = P2PKHAddress(pubkey, TestNet3)

println(legacyAddress.toString)
```
11 changes: 7 additions & 4 deletions docs/core/core-intro.md
Expand Up @@ -76,7 +76,7 @@ Transactions are run through the interpreter to check their validity. These are

Here is an example of a transaction spending a `scriptPubKey` which is correctly evaluated with our interpreter implementation:

```scala mdoc:silent:reset
```scala mdoc:invisible
import org.bitcoins.core.protocol.script._
import org.bitcoins.core.protocol.transaction._
import org.bitcoins.core.script._
Expand All @@ -85,6 +85,9 @@ import org.bitcoins.core.policy._
import org.bitcoins.core.number._
import org.bitcoins.core.crypto._
import org.bitcoins.core.currency._
```

```scala mdoc:to-string

val spendingTx = Transaction.fromHex("0100000001ccf318f0cbac588a680bbad075aebdda1f211c94ba28125b0f627f9248310db3000000006b4830450221008337ce3ce0c6ac0ab72509f889c1d52701817a2362d6357457b63e3bdedc0c0602202908963b9cf1a095ab3b34b95ce2bc0d67fb0f19be1cc5f7b3de0b3a325629bf01210241d746ca08da0a668735c3e01c1fa02045f2f399c5937079b6434b5a31dfe353ffffffff0210335d05000000001976a914b1d7591b69e9def0feb13254bace942923c7922d88ac48030000000000001976a9145e690c865c2f6f7a9710a474154ab1423abb5b9288ac00000000")

Expand All @@ -97,8 +100,8 @@ val inputIndex = UInt32.zero
val btxsc = BaseTxSigComponent(spendingTx,inputIndex,output,Policy.standardScriptVerifyFlags)

val preExecution = PreExecutionScriptProgram(btxsc)
```

```scala mdoc
val result = ScriptInterpreter.run(preExecution)
```

println(s"Script execution result=${result}")
```
6 changes: 4 additions & 2 deletions docs/core/psbts.md
Expand Up @@ -16,15 +16,17 @@ creation, updating, combining, signing, finalizing,
and transaction extraction.

An example on a typical PSBT workflow:

```scala mdoc:to-string
```scala mdoc:invisible
import org.bitcoins.core.crypto.ECPrivateKey
import org.bitcoins.core.protocol.script.ScriptPubKey
import org.bitcoins.core.protocol.transaction.{BaseTransaction, Transaction}
import org.bitcoins.core.psbt.PSBT
import org.bitcoins.core.script.crypto.HashType
import scodec.bits._
import scala.concurrent.{ExecutionContext, ExecutionContextExecutor}
```

```scala mdoc:to-string
implicit val ec: ExecutionContextExecutor = ExecutionContext.global

// First you need an unsigned transaction,
Expand Down
8 changes: 6 additions & 2 deletions docs/core/txbuilder.md
Expand Up @@ -6,7 +6,7 @@ title: TxBuilder example
Bitcoin-S features a transaction builder that constructs and signs Bitcoin
transactions. Here's an example of how to use it

```scala mdoc:silent
```scala mdoc:invisible
import scala.concurrent._
import scala.concurrent.duration._

Expand All @@ -23,6 +23,10 @@ import wallet.builder._
import wallet.fee._
import wallet.utxo._

```

```scala mdoc:to-string

implicit val ec: ExecutionContext = ExecutionContext.Implicits.global

// generate a fresh private key that we are going to use in the scriptpubkey
Expand Down Expand Up @@ -124,7 +128,7 @@ val signedTx: Transaction = {
}
```

```scala mdoc
```scala mdoc:to-string
signedTx.inputs.length

signedTx.outputs.length
Expand Down
16 changes: 9 additions & 7 deletions docs/key-manager/key-manager.md
Expand Up @@ -26,7 +26,7 @@ A popular way for bitcoin wallet's to represent entropy is [BIP39](https://githu

You can generate a `MnemonicCode` in bitcoin-s with the following code

```scala mdoc
```scala mdoc:to-string
import org.bitcoins.core.crypto._

//get 256 bits of random entropy
Expand All @@ -48,12 +48,10 @@ generate specific kinds of addresses for wallets.
3. [`network`](../../core/src/main/scala/org/bitcoins/core/config/NetworkParameters.scala) what cryptocurrency network this key manager is associated with


This controls how the root key is defined. The combination of `purpose` and `network` determine how the root `ExtKey` is serialized. For more information on how this works please see [hd-keys](hd-keys.md)
This controls how the root key is defined. The combination of `purpose` and `network` determine how the root `ExtKey` is serialized. For more information on how this works please see [hd-keys](../core/hd-keys.md)

Now we can construct a native segwit key manager for the regtest network!

```scala mdoc

```scala mdoc:invisible
import org.bitcoins.core.crypto._

import org.bitcoins.core.config._
Expand All @@ -66,6 +64,10 @@ import org.bitcoins.keymanager.bip39._

import java.nio.file._

```

```scala mdoc:to-string

//this will create a temp directory with the prefix 'key-manager-example` that will
//have a file in it called "encrypted-bitcoin-s-seed.json"
val seedPath = Files.createTempDirectory("key-manager-example").resolve(WalletStorage.ENCRYPTED_SEED_FILE_NAME)
Expand Down Expand Up @@ -94,13 +96,13 @@ which is a native segwit `ExtPubKey` for the regtest network!
You can always change the `network` or `purpose` to support different things. You do _not_ need to initialize the key manager
again after initializing it once. You can use the same `mnemonic` for different networks, which you control `KeyManagerParams`.

```scala
```scala mdoc:to-string

//let's create a nested segwit key manager for mainnet
val mainnetKmParams = KeyManagerParams(seedPath, HDPurposes.SegWit, MainNet)

//we do not need to all `initializeWithMnemonic()` again as we have saved the seed to dis
val mainnetKeyManager = KeyManager(mnemonic, mainnetKmParams)
val mainnetKeyManager = BIP39KeyManager(mnemonic, mainnetKmParams, None)

val mainnetXpub = mainnetKeyManager.getRootXPub

Expand Down

0 comments on commit 89f1db6

Please sign in to comment.