Browse Source

Merge pull request #48 from Bucko13/integrate-slate

Integrate slate
nov-updates
Buck Perley 7 years ago
committed by GitHub
parent
commit
9c07a89ca9
  1. 11
      .travis.yml
  2. 11
      api-docs-slate/Gemfile
  3. 129
      api-docs-slate/Gemfile.lock
  4. 13
      api-docs-slate/LICENSE
  5. 114
      api-docs-slate/README.md
  6. 57
      api-docs-slate/config.rb
  7. 148
      api-docs-slate/font-selection.json
  8. 16
      api-docs-slate/lib/multilang.rb
  9. 30
      api-docs-slate/lib/toc_data.rb
  10. 17
      api-docs-slate/lib/unique_head.rb
  11. BIN
      api-docs-slate/source/fonts/slate.eot
  12. 14
      api-docs-slate/source/fonts/slate.svg
  13. BIN
      api-docs-slate/source/fonts/slate.ttf
  14. BIN
      api-docs-slate/source/fonts/slate.woff
  15. BIN
      api-docs-slate/source/fonts/slate.woff2
  16. BIN
      api-docs-slate/source/images/logo.png
  17. BIN
      api-docs-slate/source/images/navbar.png
  18. 106
      api-docs-slate/source/includes/_clients.md
  19. 218
      api-docs-slate/source/includes/_coin.md
  20. 4
      api-docs-slate/source/includes/_errors.md
  21. 294
      api-docs-slate/source/includes/_node.md
  22. 52
      api-docs-slate/source/includes/_node_rpc.md
  23. 581
      api-docs-slate/source/includes/_node_rpc_block.md
  24. 144
      api-docs-slate/source/includes/_node_rpc_chain.md
  25. 541
      api-docs-slate/source/includes/_node_rpc_general.md
  26. 651
      api-docs-slate/source/includes/_node_rpc_mempool.md
  27. 638
      api-docs-slate/source/includes/_node_rpc_mining.md
  28. 614
      api-docs-slate/source/includes/_node_rpc_network.md
  29. 680
      api-docs-slate/source/includes/_node_rpc_tx.md
  30. 336
      api-docs-slate/source/includes/_transaction.md
  31. 1888
      api-docs-slate/source/includes/_wallet.md
  32. 231
      api-docs-slate/source/includes/_wallet_accounts.md
  33. 162
      api-docs-slate/source/includes/_wallet_admin.md
  34. 309
      api-docs-slate/source/includes/_wallet_tx.md
  35. 80
      api-docs-slate/source/index.html.md
  36. 2
      api-docs-slate/source/javascripts/all.js
  37. 16
      api-docs-slate/source/javascripts/all_nosearch.js
  38. 164
      api-docs-slate/source/javascripts/app/_lang.js
  39. 98
      api-docs-slate/source/javascripts/app/_search.js
  40. 117
      api-docs-slate/source/javascripts/app/_toc.js
  41. 169
      api-docs-slate/source/javascripts/lib/_energize.js
  42. 7
      api-docs-slate/source/javascripts/lib/_imagesloaded.min.js
  43. 108
      api-docs-slate/source/javascripts/lib/_jquery.highlight.js
  44. 9831
      api-docs-slate/source/javascripts/lib/_jquery.js
  45. 1910
      api-docs-slate/source/javascripts/lib/_lunr.js
  46. 122
      api-docs-slate/source/layouts/layout.erb
  47. 48
      api-docs-slate/source/stylesheets/_custom.scss
  48. 38
      api-docs-slate/source/stylesheets/_icon-font.scss
  49. 427
      api-docs-slate/source/stylesheets/_normalize.scss
  50. 103
      api-docs-slate/source/stylesheets/_variables.scss
  51. 147
      api-docs-slate/source/stylesheets/print.css.scss
  52. 616
      api-docs-slate/source/stylesheets/screen.css.scss
  53. 2
      api-docs/index.html
  54. 6
      build-api.sh
  55. 22
      guides.html
  56. 17
      guides/crowdfund-tx.html
  57. 1
      guides/generate-address.html
  58. 3
      guides/install-linux.html
  59. 1
      guides/install-mac.html
  60. 1
      guides/install-windows.html
  61. 1
      guides/multisig-tx.html
  62. 2
      guides/op_return.html
  63. 2
      guides/scripting.html
  64. 699
      guides/wallets.html
  65. 2
      guides/working-with-txs.html

11
.travis.yml

@ -1,9 +1,14 @@
language: node_js
node_js:
- stable
- stable
before_install:
- rvm get stable
- rvm use ruby --install --default
before_script:
- npm run clear-guides
- npm run convert-markdown -- --all
- npm run clear-guides
- npm run convert-markdown -- --all
script:
- sh ./build-api.sh
deploy:
provider: pages
skip_cleanup: true

11
api-docs-slate/Gemfile

@ -0,0 +1,11 @@
ruby '>=2.3.1'
source 'https://rubygems.org'
# Middleman
gem 'middleman', '~>4.2.1'
gem 'middleman-syntax', '~> 3.0.0'
gem 'middleman-autoprefixer', '~> 2.7.0'
gem "middleman-sprockets", "~> 4.1.0"
gem 'rouge', '~> 2.0.5'
gem 'redcarpet', '~> 3.4.0'
gem 'nokogiri', '~> 1.6.8'

129
api-docs-slate/Gemfile.lock

@ -0,0 +1,129 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (5.0.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (~> 0.7)
minitest (~> 5.1)
tzinfo (~> 1.1)
addressable (2.5.0)
public_suffix (~> 2.0, >= 2.0.2)
autoprefixer-rails (6.6.1)
execjs
backports (3.6.8)
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.12.2)
compass-import-once (1.0.5)
sass (>= 3.2, < 3.5)
concurrent-ruby (1.0.4)
contracts (0.13.0)
dotenv (2.2.0)
erubis (2.7.0)
execjs (2.7.0)
fast_blank (1.0.0)
fastimage (2.0.1)
addressable (~> 2)
ffi (1.9.17)
haml (4.0.7)
tilt
hamster (3.0.0)
concurrent-ruby (~> 1.0)
hashie (3.5.1)
i18n (0.7.0)
kramdown (1.13.2)
listen (3.0.8)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
memoist (0.15.0)
middleman (4.2.1)
coffee-script (~> 2.2)
compass-import-once (= 1.0.5)
haml (>= 4.0.5)
kramdown (~> 1.2)
middleman-cli (= 4.2.1)
middleman-core (= 4.2.1)
sass (>= 3.4.0, < 4.0)
middleman-autoprefixer (2.7.1)
autoprefixer-rails (>= 6.5.2, < 7.0.0)
middleman-core (>= 3.3.3)
middleman-cli (4.2.1)
thor (>= 0.17.0, < 2.0)
middleman-core (4.2.1)
activesupport (>= 4.2, < 5.1)
addressable (~> 2.3)
backports (~> 3.6)
bundler (~> 1.1)
contracts (~> 0.13.0)
dotenv
erubis
execjs (~> 2.0)
fast_blank
fastimage (~> 2.0)
hamster (~> 3.0)
hashie (~> 3.4)
i18n (~> 0.7.0)
listen (~> 3.0.0)
memoist (~> 0.14)
padrino-helpers (~> 0.13.0)
parallel
rack (>= 1.4.5, < 3)
sass (>= 3.4)
servolux
tilt (~> 2.0)
uglifier (~> 3.0)
middleman-sprockets (4.1.0)
middleman-core (~> 4.0)
sprockets (>= 3.0)
middleman-syntax (3.0.0)
middleman-core (>= 3.2)
rouge (~> 2.0)
mini_portile2 (2.1.0)
minitest (5.10.1)
nokogiri (1.6.8.1)
mini_portile2 (~> 2.1.0)
padrino-helpers (0.13.3.3)
i18n (~> 0.6, >= 0.6.7)
padrino-support (= 0.13.3.3)
tilt (>= 1.4.1, < 3)
padrino-support (0.13.3.3)
activesupport (>= 3.1)
parallel (1.10.0)
public_suffix (2.0.5)
rack (2.0.1)
rb-fsevent (0.9.8)
rb-inotify (0.9.8)
ffi (>= 0.5.0)
redcarpet (3.4.0)
rouge (2.0.7)
sass (3.4.23)
servolux (0.12.0)
sprockets (3.7.1)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
thor (0.19.4)
thread_safe (0.3.5)
tilt (2.0.6)
tzinfo (1.2.2)
thread_safe (~> 0.1)
uglifier (3.0.4)
execjs (>= 0.3.0, < 3)
PLATFORMS
ruby
DEPENDENCIES
middleman (~> 4.2.1)
middleman-autoprefixer (~> 2.7.0)
middleman-sprockets (~> 4.1.0)
middleman-syntax (~> 3.0.0)
nokogiri (~> 1.6.8)
redcarpet (~> 3.4.0)
rouge (~> 2.0.5)
RUBY VERSION
ruby 2.3.3p222
BUNDLED WITH
1.14.5

13
api-docs-slate/LICENSE

@ -0,0 +1,13 @@
Copyright 2008-2013 Concur Technologies, Inc.
Licensed under the Apache License, Version 2.0 (the "License"); you may
not use this file except in compliance with the License. You may obtain
a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations
under the License.

114
api-docs-slate/README.md

@ -0,0 +1,114 @@
<p align="center">
<img src="https://raw.githubusercontent.com/lord/img/master/logo-slate.png" alt="Slate: API Documentation Generator" width="226">
<br>
<a href="https://travis-ci.org/lord/slate"><img src="https://travis-ci.org/lord/slate.svg?branch=master" alt="Build Status"></a>
</p>
<p align="center">Slate helps you create beautiful, intelligent, responsive API documentation.</p>
<p align="center"><img src="https://raw.githubusercontent.com/lord/img/master/screenshot-slate.png" width=700 alt="Screenshot of Example Documentation created with Slate"></p>
<p align="center"><em>The example above was created with Slate. Check it out at <a href="https://lord.github.io/slate">lord.github.io/slate</a>.</em></p>
Features
------------
* **Clean, intuitive design** — With Slate, the description of your API is on the left side of your documentation, and all the code examples are on the right side. Inspired by [Stripe's](https://stripe.com/docs/api) and [Paypal's](https://developer.paypal.com/webapps/developer/docs/api/) API docs. Slate is responsive, so it looks great on tablets, phones, and even in print.
* **Everything on a single page** — Gone are the days when your users had to search through a million pages to find what they wanted. Slate puts the entire documentation on a single page. We haven't sacrificed linkability, though. As you scroll, your browser's hash will update to the nearest header, so linking to a particular point in the documentation is still natural and easy.
* **Slate is just Markdown** — When you write docs with Slate, you're just writing Markdown, which makes it simple to edit and understand. Everything is written in Markdown — even the code samples are just Markdown code blocks.
* **Write code samples in multiple languages** — If your API has bindings in multiple programming languages, you can easily put in tabs to switch between them. In your document, you'll distinguish different languages by specifying the language name at the top of each code block, just like with Github Flavored Markdown.
* **Out-of-the-box syntax highlighting** for [over 100 languages](https://github.com/jneen/rouge/wiki/List-of-supported-languages-and-lexers), no configuration required.
* **Automatic, smoothly scrolling table of contents** on the far left of the page. As you scroll, it displays your current position in the document. It's fast, too. We're using Slate at TripIt to build documentation for our new API, where our table of contents has over 180 entries. We've made sure that the performance remains excellent, even for larger documents.
* **Let your users update your documentation for you** — By default, your Slate-generated documentation is hosted in a public Github repository. Not only does this mean you get free hosting for your docs with Github Pages, but it also makes it simple for other developers to make pull requests to your docs if they find typos or other problems. Of course, if you don't want to use GitHub, you're also welcome to host your docs elsewhere.
Getting started with Slate is super easy! Simply fork this repository and follow the instructions below. Or, if you'd like to check out what Slate is capable of, take a look at the [sample docs](http://lord.github.io/slate).
Getting Started with Slate
------------------------------
### Prerequisites
You're going to need:
- **Linux or OS X** — Windows may work, but is unsupported.
- **Ruby, version 2.3.1 or newer**
- **Bundler** — If Ruby is already installed, but the `bundle` command doesn't work, just run `gem install bundler` in a terminal.
### Getting Set Up
1. Fork this repository on Github.
2. Clone *your forked repository* (not our original one) to your hard drive with `git clone https://github.com/YOURUSERNAME/slate.git`
3. `cd slate`
4. Initialize and start Slate. You can either do this locally, or with Vagrant:
```shell
# either run this to run locally
bundle install
bundle exec middleman server
# OR run this to run with vagrant
vagrant up
```
You can now see the docs at http://localhost:4567. Whoa! That was fast!
Now that Slate is all set up on your machine, you'll probably want to learn more about [editing Slate markdown](https://github.com/lord/slate/wiki/Markdown-Syntax), or [how to publish your docs](https://github.com/lord/slate/wiki/Deploying-Slate).
If you'd prefer to use Docker, instructions are available [in the wiki](https://github.com/lord/slate/wiki/Docker).
### Note on JavaScript Runtime
For those who don't have JavaScript runtime or are experiencing JavaScript runtime issues with ExecJS, it is recommended to add the [rubyracer gem](https://github.com/cowboyd/therubyracer) to your gemfile and run `bundle` again.
Companies Using Slate
---------------------------------
* [NASA](https://api.nasa.gov)
* [IBM](https://docs.cloudant.com/api.html)
* [Sony](http://developers.cimediacloud.com)
* [Best Buy](https://bestbuyapis.github.io/api-documentation/)
* [Travis-CI](https://docs.travis-ci.com/api/)
* [Greenhouse](https://developers.greenhouse.io/harvest.html)
* [Woocommerce](http://woocommerce.github.io/woocommerce-rest-api-docs/)
* [Appium](http://appium.io/slate/en/master)
* [Dwolla](https://docs.dwolla.com/)
* [Clearbit](https://clearbit.com/docs)
* [Coinbase](https://developers.coinbase.com/api)
* [Parrot Drones](http://developer.parrot.com/docs/bebop/)
* [Fidor Bank](http://docs.fidor.de/)
* [Scale](https://docs.scaleapi.com/)
You can view more in [the list on the wiki](https://github.com/lord/slate/wiki/Slate-in-the-Wild).
Need Help? Found a bug?
--------------------
[Submit an issue](https://github.com/lord/slate/issues) to the Slate Github if you need any help. And, of course, feel free to submit pull requests with bug fixes or changes.
Contributors
--------------------
Slate was built by [Robert Lord](https://lord.io) while interning at [TripIt](https://www.tripit.com/).
Thanks to the following people who have submitted major pull requests:
- [@chrissrogers](https://github.com/chrissrogers)
- [@bootstraponline](https://github.com/bootstraponline)
- [@realityking](https://github.com/realityking)
- [@cvkef](https://github.com/cvkef)
Also, thanks to [Sauce Labs](http://saucelabs.com) for sponsoring the development of the responsive styles.
Special Thanks
--------------------
- [Middleman](https://github.com/middleman/middleman)
- [jquery.tocify.js](https://github.com/gfranko/jquery.tocify.js)
- [middleman-syntax](https://github.com/middleman/middleman-syntax)
- [middleman-gh-pages](https://github.com/edgecase/middleman-gh-pages)
- [Font Awesome](http://fortawesome.github.io/Font-Awesome/)

57
api-docs-slate/config.rb

@ -0,0 +1,57 @@
# Unique header generation
require './lib/unique_head.rb'
# Markdown
set :markdown_engine, :redcarpet
set :markdown,
fenced_code_blocks: true,
smartypants: true,
disable_indented_code_blocks: true,
prettify: true,
tables: true,
with_toc_data: true,
no_intra_emphasis: true,
renderer: UniqueHeadCounter
# Assets
set :css_dir, 'stylesheets'
set :js_dir, 'javascripts'
set :images_dir, 'images'
set :fonts_dir, 'fonts'
# Activate the syntax highlighter
activate :syntax
ready do
require './lib/multilang.rb'
end
activate :sprockets
activate :autoprefixer do |config|
config.browsers = ['last 2 version', 'Firefox ESR']
config.cascade = false
config.inline = true
end
# Github pages require relative links
activate :relative_assets
set :relative_links, true
# Build Configuration
configure :build do
# If you're having trouble with Middleman hanging, commenting
# out the following two lines has been known to help
activate :minify_css
activate :minify_javascript
# activate :relative_assets
# activate :asset_hash
# activate :gzip
end
# Deploy Configuration
# If you want Middleman to listen on a different port, you can set that below
set :port, 4567
helpers do
require './lib/toc_data.rb'
end

148
api-docs-slate/font-selection.json

@ -0,0 +1,148 @@
{
"IcoMoonType": "selection",
"icons": [
{
"icon": {
"paths": [
"M438.857 73.143q119.429 0 220.286 58.857t159.714 159.714 58.857 220.286-58.857 220.286-159.714 159.714-220.286 58.857-220.286-58.857-159.714-159.714-58.857-220.286 58.857-220.286 159.714-159.714 220.286-58.857zM512 785.714v-108.571q0-8-5.143-13.429t-12.571-5.429h-109.714q-7.429 0-13.143 5.714t-5.714 13.143v108.571q0 7.429 5.714 13.143t13.143 5.714h109.714q7.429 0 12.571-5.429t5.143-13.429zM510.857 589.143l10.286-354.857q0-6.857-5.714-10.286-5.714-4.571-13.714-4.571h-125.714q-8 0-13.714 4.571-5.714 3.429-5.714 10.286l9.714 354.857q0 5.714 5.714 10t13.714 4.286h105.714q8 0 13.429-4.286t6-10z"
],
"attrs": [],
"isMulticolor": false,
"tags": [
"exclamation-circle"
],
"defaultCode": 61546,
"grid": 14
},
"attrs": [],
"properties": {
"id": 100,
"order": 4,
"prevSize": 28,
"code": 58880,
"name": "exclamation-sign",
"ligatures": ""
},
"setIdx": 0,
"iconIdx": 0
},
{
"icon": {
"paths": [
"M585.143 786.286v-91.429q0-8-5.143-13.143t-13.143-5.143h-54.857v-292.571q0-8-5.143-13.143t-13.143-5.143h-182.857q-8 0-13.143 5.143t-5.143 13.143v91.429q0 8 5.143 13.143t13.143 5.143h54.857v182.857h-54.857q-8 0-13.143 5.143t-5.143 13.143v91.429q0 8 5.143 13.143t13.143 5.143h256q8 0 13.143-5.143t5.143-13.143zM512 274.286v-91.429q0-8-5.143-13.143t-13.143-5.143h-109.714q-8 0-13.143 5.143t-5.143 13.143v91.429q0 8 5.143 13.143t13.143 5.143h109.714q8 0 13.143-5.143t5.143-13.143zM877.714 512q0 119.429-58.857 220.286t-159.714 159.714-220.286 58.857-220.286-58.857-159.714-159.714-58.857-220.286 58.857-220.286 159.714-159.714 220.286-58.857 220.286 58.857 159.714 159.714 58.857 220.286z"
],
"attrs": [],
"isMulticolor": false,
"tags": [
"info-circle"
],
"defaultCode": 61530,
"grid": 14
},
"attrs": [],
"properties": {
"id": 85,
"order": 3,
"name": "info-sign",
"prevSize": 28,
"code": 58882
},
"setIdx": 0,
"iconIdx": 2
},
{
"icon": {
"paths": [
"M733.714 419.429q0-16-10.286-26.286l-52-51.429q-10.857-10.857-25.714-10.857t-25.714 10.857l-233.143 232.571-129.143-129.143q-10.857-10.857-25.714-10.857t-25.714 10.857l-52 51.429q-10.286 10.286-10.286 26.286 0 15.429 10.286 25.714l206.857 206.857q10.857 10.857 25.714 10.857 15.429 0 26.286-10.857l310.286-310.286q10.286-10.286 10.286-25.714zM877.714 512q0 119.429-58.857 220.286t-159.714 159.714-220.286 58.857-220.286-58.857-159.714-159.714-58.857-220.286 58.857-220.286 159.714-159.714 220.286-58.857 220.286 58.857 159.714 159.714 58.857 220.286z"
],
"attrs": [],
"isMulticolor": false,
"tags": [
"check-circle"
],
"defaultCode": 61528,
"grid": 14
},
"attrs": [],
"properties": {
"id": 83,
"order": 9,
"prevSize": 28,
"code": 58886,
"name": "ok-sign"
},
"setIdx": 0,
"iconIdx": 6
},
{
"icon": {
"paths": [
"M658.286 475.429q0-105.714-75.143-180.857t-180.857-75.143-180.857 75.143-75.143 180.857 75.143 180.857 180.857 75.143 180.857-75.143 75.143-180.857zM950.857 950.857q0 29.714-21.714 51.429t-51.429 21.714q-30.857 0-51.429-21.714l-196-195.429q-102.286 70.857-228 70.857-81.714 0-156.286-31.714t-128.571-85.714-85.714-128.571-31.714-156.286 31.714-156.286 85.714-128.571 128.571-85.714 156.286-31.714 156.286 31.714 128.571 85.714 85.714 128.571 31.714 156.286q0 125.714-70.857 228l196 196q21.143 21.143 21.143 51.429z"
],
"width": 951,
"attrs": [],
"isMulticolor": false,
"tags": [
"search"
],
"defaultCode": 61442,
"grid": 14
},
"attrs": [],
"properties": {
"id": 2,
"order": 1,
"prevSize": 28,
"code": 58887,
"name": "icon-search"
},
"setIdx": 0,
"iconIdx": 7
}
],
"height": 1024,
"metadata": {
"name": "slate",
"license": "SIL OFL 1.1"
},
"preferences": {
"showGlyphs": true,
"showQuickUse": true,
"showQuickUse2": true,
"showSVGs": true,
"fontPref": {
"prefix": "icon-",
"metadata": {
"fontFamily": "slate",
"majorVersion": 1,
"minorVersion": 0,
"description": "Based on FontAwesome",
"license": "SIL OFL 1.1"
},
"metrics": {
"emSize": 1024,
"baseline": 6.25,
"whitespace": 50
},
"resetPoint": 58880,
"showSelector": false,
"selector": "class",
"classSelector": ".icon",
"showMetrics": false,
"showMetadata": true,
"showVersion": true,
"ie7": false
},
"imagePref": {
"prefix": "icon-",
"png": true,
"useClassSelector": true,
"color": 4473924,
"bgColor": 16777215
},
"historySize": 100,
"showCodes": true,
"gridSize": 16,
"showLiga": false
}
}

16
api-docs-slate/lib/multilang.rb

@ -0,0 +1,16 @@
module Multilang
def block_code(code, full_lang_name)
if full_lang_name
parts = full_lang_name.split('--')
rouge_lang_name = (parts) ? parts[0] : "" # just parts[0] here causes null ref exception when no language specified
super(code, rouge_lang_name).sub("highlight #{rouge_lang_name}") do |match|
match + " tab-" + full_lang_name
end
else
super(code, full_lang_name)
end
end
end
require 'middleman-core/renderers/redcarpet'
Middleman::Renderers::MiddlemanRedcarpetHTML.send :include, Multilang

30
api-docs-slate/lib/toc_data.rb

@ -0,0 +1,30 @@
require 'nokogiri'
def toc_data(page_content)
html_doc = Nokogiri::HTML::DocumentFragment.parse(page_content)
# get a flat list of headers
headers = []
html_doc.css('h1, h2, h3').each do |header|
headers.push({
id: header.attribute('id').to_s,
content: header.children,
level: header.name[1].to_i,
children: []
})
end
[3,2].each do |header_level|
header_to_nest = nil
headers = headers.reject do |header|
if header[:level] == header_level
header_to_nest[:children].push header if header_to_nest
true
else
header_to_nest = header if header[:level] < header_level
false
end
end
end
headers
end

17
api-docs-slate/lib/unique_head.rb

@ -0,0 +1,17 @@
# Unique header generation
require 'middleman-core/renderers/redcarpet'
class UniqueHeadCounter < Middleman::Renderers::MiddlemanRedcarpetHTML
def initialize
super
@head_count = {}
end
def header(text, header_level)
friendly_text = text.parameterize
@head_count[friendly_text] ||= 0
@head_count[friendly_text] += 1
if @head_count[friendly_text] > 1
friendly_text += "-#{@head_count[friendly_text]}"
end
return "<h#{header_level} id='#{friendly_text}'>#{text}</h#{header_level}>"
end
end

BIN
api-docs-slate/source/fonts/slate.eot

Binary file not shown.

14
api-docs-slate/source/fonts/slate.svg

@ -0,0 +1,14 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Generated by IcoMoon</metadata>
<defs>
<font id="slate" horiz-adv-x="1024">
<font-face units-per-em="1024" ascent="960" descent="-64" />
<missing-glyph horiz-adv-x="1024" />
<glyph unicode="&#x20;" d="" horiz-adv-x="512" />
<glyph unicode="&#xe600;" d="M438.857 877.714q119.429 0 220.286-58.857t159.714-159.714 58.857-220.286-58.857-220.286-159.714-159.714-220.286-58.857-220.286 58.857-159.714 159.714-58.857 220.286 58.857 220.286 159.714 159.714 220.286 58.857zM512 165.143v108.571q0 8-5.143 13.429t-12.571 5.429h-109.714q-7.429 0-13.143-5.714t-5.714-13.143v-108.571q0-7.429 5.714-13.143t13.143-5.714h109.714q7.429 0 12.571 5.429t5.143 13.429zM510.857 361.714l10.286 354.857q0 6.857-5.714 10.286-5.714 4.571-13.714 4.571h-125.714q-8 0-13.714-4.571-5.714-3.429-5.714-10.286l9.714-354.857q0-5.714 5.714-10t13.714-4.286h105.714q8 0 13.429 4.286t6 10z" />
<glyph unicode="&#xe602;" d="M585.143 164.571v91.429q0 8-5.143 13.143t-13.143 5.143h-54.857v292.571q0 8-5.143 13.143t-13.143 5.143h-182.857q-8 0-13.143-5.143t-5.143-13.143v-91.429q0-8 5.143-13.143t13.143-5.143h54.857v-182.857h-54.857q-8 0-13.143-5.143t-5.143-13.143v-91.429q0-8 5.143-13.143t13.143-5.143h256q8 0 13.143 5.143t5.143 13.143zM512 676.571v91.429q0 8-5.143 13.143t-13.143 5.143h-109.714q-8 0-13.143-5.143t-5.143-13.143v-91.429q0-8 5.143-13.143t13.143-5.143h109.714q8 0 13.143 5.143t5.143 13.143zM877.714 438.857q0-119.429-58.857-220.286t-159.714-159.714-220.286-58.857-220.286 58.857-159.714 159.714-58.857 220.286 58.857 220.286 159.714 159.714 220.286 58.857 220.286-58.857 159.714-159.714 58.857-220.286z" />
<glyph unicode="&#xe606;" d="M733.714 531.428q0 16-10.286 26.286l-52 51.429q-10.857 10.857-25.714 10.857t-25.714-10.857l-233.143-232.571-129.143 129.143q-10.857 10.857-25.714 10.857t-25.714-10.857l-52-51.429q-10.286-10.286-10.286-26.286 0-15.429 10.286-25.714l206.857-206.857q10.857-10.857 25.714-10.857 15.429 0 26.286 10.857l310.286 310.286q10.286 10.286 10.286 25.714zM877.714 438.857q0-119.429-58.857-220.286t-159.714-159.714-220.286-58.857-220.286 58.857-159.714 159.714-58.857 220.286 58.857 220.286 159.714 159.714 220.286 58.857 220.286-58.857 159.714-159.714 58.857-220.286z" />
<glyph unicode="&#xe607;" d="M658.286 475.428q0 105.714-75.143 180.857t-180.857 75.143-180.857-75.143-75.143-180.857 75.143-180.857 180.857-75.143 180.857 75.143 75.143 180.857zM950.857 0q0-29.714-21.714-51.429t-51.429-21.714q-30.857 0-51.429 21.714l-196 195.429q-102.286-70.857-228-70.857-81.714 0-156.286 31.714t-128.571 85.714-85.714 128.571-31.714 156.286 31.714 156.286 85.714 128.571 128.571 85.714 156.286 31.714 156.286-31.714 128.571-85.714 85.714-128.571 31.714-156.286q0-125.714-70.857-228l196-196q21.143-21.143 21.143-51.429z" horiz-adv-x="951" />
</font></defs></svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
api-docs-slate/source/fonts/slate.ttf

Binary file not shown.

BIN
api-docs-slate/source/fonts/slate.woff

Binary file not shown.

BIN
api-docs-slate/source/fonts/slate.woff2

Binary file not shown.

BIN
api-docs-slate/source/images/logo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
api-docs-slate/source/images/navbar.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

106
api-docs-slate/source/includes/_clients.md

@ -0,0 +1,106 @@
# Configuring Clients
## Default Listeners
```shell--visible
# With curl you just send HTTP Requests based on further docs
# Only thing to have in mind is Authentication, which is described in Auth section.
curl http://127.0.0.1:18332/ # will get info from testnet
```
By default API listens on these addresses:
Network | API Port
--------- | -----------
main | 8332
testnet | 18332
regtest | 48332
simnet | 18556
You can interact with bcoin with REST Api as well as RPC,
there are couple of ways you can use API.
- `bcoin cli` - has almost all methods described to be used.
- `javascript` - Clients used by `bcoin cli` can be used directly from javascript
- `curl` - or you can use direct HTTP calls for invoking REST/RPC API calls.
## Configuring BCOIN CLI
```shell--visible
# You can use config file
bcoin cli --config /full/path/to/bcoin.conf
# Or with prefix (which will later load bcoin.conf file from the directory)
bcoin cli --prefix /full/path/to/bcoin/dir
# You can configure it by passing arguments:
bcoin cli --network=regtest info
bcoin cli info --network=regtest
# Or use ENV variables (Starting with BCOIN_)
export BCOIN_NETWORK=regtest
export BCOIN_API_KEY=yoursecret
bcoin cli info
```
`bcoin cli` can be configured with many params:
### General configurations are:
Config | Options | Description
--------- | ----------- | -----------
prefix | dir path | This accepts directory where DBs and `bcoin.conf` are located.
network | `main`, `testnet`, `regtest` | This will configure which network to load, also where to look for config file
uri, url | Base HTTP URI | This can be used for custom port
api-key | secret | Secret used by RPC for auth.
### Wallet Specific
Config | Options | Description
--------- | ----------- | -----------
id | primary, custom | specify which account to use by default
token | token str | Token specific wallet
<aside class="notice">
Some commands might accept additional parameters.
</aside>
## Using Javascript Client
```javascript--visible
const bcoin = require('bcoin');
const Client = bcoin.http.Client;
const Wallet = bcoin.http.Wallet;
const client = new Client({
network: 'testnet',
uri: 'http://localhost:18332'
});
const wallet = new Wallet({
network: 'testnet',
uri: 'http://localhost:18332',
id: 'primary'
});
```
You can also use api with Javascript Library (used by `bcoin cli`).
There are two objects: `bcoin.http.Client` for general API and `bcoin.http.Wallet` for wallet API.
`bcoin.http.Client` options:
Config | Type | Description
--------- | ----------- | -----------
network | `main`, `testnet`, `regtest` | Network to use (doesn't lookup configs by itself)
uri | String | URI of the service
apiKey | String | api secret
`bcoin.http.Wallet` options:
Config | Type | Description
--------- | ----------- | -----------
network | `main`, `testnet`, `regtest` | Network to use (doesn't lookup configs by itself)
uri | String | URI of the service
apiKey | String | api secret
id | primary, custom | specify which account to use by default
token | token str | Token specific wallet

218
api-docs-slate/source/includes/_coin.md

@ -0,0 +1,218 @@
# Coin
Getting coin information via APi.
*Coin stands for UTXO*
<aside class="info">
You need to enable <code>index-tx</code> and <code>index-address</code> in order
to lookup coins by transaction hashes and addresses, respectively.
</aside>
## Get coin by Outpoint
```javascript
let hash, index;
```
```shell--vars
hash='c13039f53247f9ca14206da079bcf738d91bc60e251ac9ebaba9ea9a862d9092';
index=0;
```
```shell--curl
curl $url/coin/$hash/$index
```
```shell--cli
bcoin cli coin $hash $index
```
```javascript
const client = new bcoin.http.Client({
network: 'testnet'
});
(async () => {
await client.open();
const coin = await client.getCoin(hash, index);
console.log(coin);
await client.close();
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON structured like this:
```json
{
"version": 1,
"height": 100019,
"value": 144709200,
"script": "76a9148fc80aadf127f6f92b6ed33404b110f851c8eca188ac",
"address": "mtdCZdNYny2U7met3umk47SoA7HMZGfsa2",
"coinbase": false,
"hash": "c13039f53247f9ca14206da079bcf738d91bc60e251ac9ebaba9ea9a862d9092",
"index": 0
}
```
Get coin by outpoint (hash and index). Returns coin in bcoin coin json format.
### HTTP Request
`GET /coin/:hash/:index`
### URL Parameters
Parameter | Description
--------- | -----------
:hash | Hash of tx
:index | Output's index in tx
## Get coins by address
```javascript
let address;
```
```shell--vars
address='n3BmXQPa1dKi3zEyCdCGNHTuE5GLdmw1Tr';
```
```shell--curl
curl $url/coin/address/$address
```
```shell--cli
bcoin cli coin $address
```
```javascript
const client = new bcoin.http.Client({
network: 'testnet'
});
(async () => {
await client.open();
const coins = await client.getCoinsByAddress(address);
console.log(coins);
await client.close();
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON structured like this:
```json
[
{
"version": 1,
"height": 502,
"value": 275391,
"script": "76a914edb1dfaf6e0b39449da811275386edf2eb54baba88ac",
"address": "n3BmXQPa1dKi3zEyCdCGNHTuE5GLdmw1Tr",
"coinbase": false,
"hash": "86150a141ebe5903a5d31e701698a01d598b81f099ea7577dad73033eab02ef9",
"index": 1
}
]
```
Get coin objects array by address.
### HTTP Request
`GET /coin/address/:address`
### URL Parameters
Parameter | Description
--------- | -----------
:address | bitcoin address
## Get coins by addresses
```javascript
let address0, address1;
```
```shell--vars
address0='n3BmXQPa1dKi3zEyCdCGNHTuE5GLdmw1Tr';
address1='mwLHWwWPDwtCBZA7Ltg9QSzKK5icdCU5rb';
```
```shell--curl
curl $url/coin/address \
-H 'Content-Type: application/json' \
-X POST \
--data '{ "addresses":[ "'$address0'", "'$address1'" ]}'
```
```shell--cli
No CLI Option.
```
```javascript
const client = new bcoin.http.Client({
network: 'testnet'
});
(async () => {
await client.open();
const coins = await client.getCoinsByAddresses([address0, address1]);
console.log(coins);
await client.close();
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON structured like this:
```json
[
{
"version": 1,
"height": 502,
"value": 275391,
"script": "76a914edb1dfaf6e0b39449da811275386edf2eb54baba88ac",
"address": "n3BmXQPa1dKi3zEyCdCGNHTuE5GLdmw1Tr",
"coinbase": false,
"hash": "86150a141ebe5903a5d31e701698a01d598b81f099ea7577dad73033eab02ef9",
"index": 1
},
{
"version": 1,
"height": 500,
"value": 1095497,
"script": "76a914ad7d7b9ac5260ad13fa55e06143283f5b36495f788ac",
"address": "mwLHWwWPDwtCBZA7Ltg9QSzKK5icdCU5rb",
"coinbase": false,
"hash": "4692772a73ea834c836915089acf97f2c790380a2b8fd32f82729da72545d8c5",
"index": 0
}
]
```
Get coins by addresses,
returns array of coin objects.
### HTTP Request
`POST /coin/address`
### POST Parameters (JSON)
Parameter | Description
--------- | -----------
addresses | List of bitcoin addresses

4
api-docs-slate/source/includes/_errors.md

@ -0,0 +1,4 @@
# Errors
Any errors will be returned with an http status code other than 200, containing a JSON object in the form:
`{"error": { message: "message" } }`

294
api-docs-slate/source/includes/_node.md

@ -0,0 +1,294 @@
# Node
## JSON-RPC Requests
Route for JSON-RPC requests, most of which mimic the bitcoind RPC calls completely.
```shell--curl
curl $url \
-H 'Content-Type: application/json' \
-X POST \
--data '{ "method": "getblockchaininfo", "params": [] }'
```
### HTTP Request
`POST /`
More about RPC Requests in RPC Docs.
## Get server info
```shell--curl
curl $url/
```
```shell--cli
bcoin cli info
```
```javascript
const client = new bcoin.http.Client({
network: 'testnet'
});
(async () => {
await client.open();
const info = await client.getInfo();
console.log(info);
await client.close();
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON structured like this:
```json
{
"version": "v1.0.0-beta.14",
"network": "testnet",
"chain": {
"height": 1157058,
"tip": "00000000000002ac70408966be53a1e01e7e014a3d4f1f275201c751de7d6e77",
"progress": 1
},
"pool": {
"host": "203.0.113.114",
"port": 18333,
"agent": "/bcoin:v1.0.0-beta.14/",
"services": "1001",
"outbound": 8,
"inbound": 0
},
"mempool": {
"tx": 39,
"size": 121512
},
"time": {
"uptime": 7403,
"system": 1502381034,
"adjusted": 1502381035,
"offset": 1
},
"memory": {
"total": 87,
"jsHeap": 23,
"jsHeapTotal": 30,
"nativeHeap": 56,
"external": 8
}
}
```
Get server Info.
### HTTP Request
<p>Get server info. No params.</p>
`GET /`
No Params.
## Get mempool snapshot
```shell--curl
curl $url/mempool
```
```shell--cli
bcoin cli mempool
```
```javascript
const client = new bcoin.http.Client({
network: 'testnet'
});
(async () => {
await client.open();
const mempoolTxs = await client.getMempool();
console.log(mempoolTxs);
await client.close();
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON structured like this:
```json
[
"9fee8350a3cc2f5bfa9d90f008af0bbc22d84aa5b1242da2f3479935f597c9ed",
"d3bd772f3b369e2e04b9b928e40dddded5ee1448b9d1ee0b6a13e6c2ae283f6a",
...
]
```
Get mempool snapshot (array of json txs).
### HTTP Request
`GET /mempool`
No Params.
## Get block by hash or height
```javascript
let blockHash, blockHeight;
```
```shell--vars
blockHash='00000000cabd2d0245add40f335bab18d3e837eccf868b64aabbbbac74fb21e0';
blockHeight='1500';
```
```shell--curl
curl $url/block/$blockHash # by hash
curl $url/block/$blockHeight # by height
```
```shell--cli
bcoin cli block $blockHash # by hash
bcoin cli block $blockHeight # by height
```
```javascript
const client = new bcoin.http.Client({
network: 'testnet'
});
(async () => {
await client.open();
const blockByHash = await client.getBlock(blockHash);
const blockByHeight = await client.getBlock(blockHeight);
console.log(blockByHash, blockByHeight);
await client.close();
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON structured like this:
```json
{
"hash": "00000000cabd2d0245add40f335bab18d3e837eccf868b64aabbbbac74fb21e0",
"height": 1500,
"version": 1,
"prevBlock": "00000000f651e7fe6d9a4845dcf40f5642216e59054453a4368a73a7295f9f3d",
"merkleRoot": "e3e4590784a828967e6d9319eca2915c1860a63167449f9605e649a0aafe6d0a",
"time": 1337966228,
"bits": 486604799,
"nonce": 2671491584,
"txs": [
{
"hash": "e3e4590784a828967e6d9319eca2915c1860a63167449f9605e649a0aafe6d0a",
"witnessHash": "e3e4590784a828967e6d9319eca2915c1860a63167449f9605e649a0aafe6d0a",
"fee": 0,
"rate": 0,
"mtime": 1502382669,
"index": 0,
"version": 1,
"flag": 1,
"inputs": [
{
"prevout": {
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
"index": 4294967295
},
"script": "0494bebf4f0108172f503253482f49636549726f6e2d51432d6d696e65722f",
"witness": "00",
"sequence": 4294967295,
"address": null
}
],
"outputs": [
{
"value": 5000000000,
"script": "21032fd2666c8d5ffae0147acc0b9628160652679663397e911170ebaf1e26358abfac",
"address": "mtohBeScUtM2ndcmmpSV8o2jcvmknp1Mpy"
}
],
"locktime": 0
}
]
}
```
Returns block info by block hash or height.
### HTTP Request
`GET /block/:blockhashOrHeight`
### URL Parameters
Parameter | Description
--------- | -----------
:blockhashOrHeight | Hash or Height of block
## Broadcast transaction
```javascript
let tx;
```
```shell--vars
tx='0100000001ff2a3afc3a8133a3bfeedd391bc3cff39d47fe4e3caee492a93f92edff76b9d4000000006a47304402204cc6a35cb3d3d976cb10e3c98df66aba29b5efc7b5ecdbc0f4ed949aa64235f20220512fce2d63739012094f12c3a9402919b32149c32d4d71a3448d4695ae8e3dc601210325c9abd8916d6e5ba0b3c501a70c0186f3bf6e4567922b9d83ae205d1d9e9affffffffff0244cff505000000001976a91423f5580d600bcfe5b99d9fe737530fd8b32492a088ac00111024010000001976a91473f3ecd665da93701358bd957393b8085c1aa2d988ac00000000';
```
```shell--curl
curl $url/broadcast \
-H 'Content-Type: application/json' \
-X POST \
--data '{ "tx": "'$tx'" }'
```
```shell--cli
bcoin cli broadcast $txhex
```
```javascript
const client = new bcoin.http.Client({
network: 'testnet',
});
(async () => {
await client.open();
const result = await client.broadcast(tx);
console.log(result);
await client.close();
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON structured like this:
```json
{
"success": true
}
```
Broadcast a transaction by adding it to the node's mempool. If mempool verification fails, the node will still forcefully advertise and relay the transaction for the next 60 seconds.
### HTTP Request
`POST /broadcast`
### POST Parameters (JSON)
Parameter | Description
--------- | -----------
tx | transaction hash

52
api-docs-slate/source/includes/_node_rpc.md

@ -0,0 +1,52 @@
# RPC Calls - Node
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{ "method": "methodname", "params": [...] "id": "some-id" }'
```
```shell--cli
bcoin cli rpc params...
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('MethodName', [ ...params ]);
// RES will return "result" part of the object, not the id or error
// error will be thrown.
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON structured like this:
> Further examples will only include "result" part.
```json
{"result": resultObject ,"error": errorObject, "id": passedID}
```
Bcoin rpc calls mimic Bitcoin Core's RPC.
This is documentation how to use it with `bcoin`.
RPC Calls are accepted at:
`POST /`
*Note: bcoin cli rpc and javascript will return error OR result.*
### POST Parameters RPC
Parameter | Description
--------- | -----------
method | Name of the RPC call
params | Parameters accepted by method
id | Will be returned with the response (Shouldn't be object)

581
api-docs-slate/source/includes/_node_rpc_block.md

@ -0,0 +1,581 @@
# RPC Calls - Block
## getblockchaininfo
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{ "method": "getblockchaininfo" }'
```
```shell--cli
bcoin cli rpc getblockchaininfo
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('getblockchaininfo');
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
{
"chain": "test",
"blocks": 1178402,
"headers": 1178402,
"bestblockhash": "0000000000000dd897f549915ba7099b6d4f86f4512801d617a7c0c655827d08",
"difficulty": 1048576,
"mediantime": 1502814951,
"verificationprogress": 1,
"chainwork": "00000000000000000000000000000000000000000000002976ca78529498e335",
"pruned": false,
"softforks": [
{
"id": "bip34",
"version": 2,
"reject": {
"status": true
}
},
{
"id": "bip66",
"version": 3,
"reject": {
"status": true
}
},
{
"id": "bip65",
"version": 4,
"reject": {
"status": true
}
}
],
"bip9_softforks": {
"csv": {
"status": "active",
"bit": 0,
"startTime": 1456790400,
"timeout": 1493596800
},
"segwit": {
"status": "active",
"bit": 1,
"startTime": 1462060800,
"timeout": 1493596800
},
"segsignal": {
"status": "defined",
"bit": 4,
"startTime": 4294967295,
"timeout": 4294967295
},
"testdummy": {
"status": "failed",
"bit": 28,
"startTime": 1199145601,
"timeout": 1230767999
}
},
"pruneheight": null
}
```
Returns blockchain information.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
None. |
## getbestblockhash
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{ "method": "getbestblockhash" }'
```
```shell--cli
bcoin cli rpc getbestblockhash
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('getbestblockhash');
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
"0000000000000225f8332239fe00b74c65f916ff71dde5dee33b72ddd3b0e237"
```
Returns Block Hash of the tip.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
None. |
## getblockcount
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{ "method": "getblockcount" }'
```
```shell--cli
bcoin cli rpc getbestblockhash
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('getblockcount');
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
1178418
```
Returns block count.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
None. ||||
## getblock
```javascript
let blockhash, details, verbose;
```
```shell--vars
blockhash='00000000e0290b7c66227c7499692aac5437860ee912424bf8eea3a3883a4e37';
verbose=1;
details=0;
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "getblock",
"params": [ "'$blockhash'", "'$verbose'", "'$details'" ]
}'
```
```shell--cli
bcoin cli rpc getblock $blockhash $verbose $details
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('getblock', [ blockhash, verbose, details ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
{
"hash": "00000000e0290b7c66227c7499692aac5437860ee912424bf8eea3a3883a4e37",
"confirmations": 1177921,
"strippedsize": 2499,
"size": 2499,
"weight": 9996,
"height": 502,
"version": 1,
"versionHex": "00000001",
"merkleroot": "4f7a9087973b891fc86cc59fd9c2cb696f7a813360d3553626dc6c38909f9571",
"coinbase": "3337346bde777ade327922b5deef5fb7f88e98cecb22",
"tx": [
"2a69b021fc6cbd61260767302781c85fb0873acf18980ea6187fc868e4a3e3f9",
"c61f2ef26bb08dcf1e16db4fece56ac92a3acac24e4dac90315e5c0ad6af67e6",
"ed8c8213cc2d214ad2f293caae99e26e2c59d158f3eda5d9c1292e0961e20e76",
"21da008d1fddc1a067d2d6cd9bb6e78acb5bdc9560252c17cfd59c331dd5c2cf",
"90cc439e0a03109c33c966d92ccd18b0509ef678458d85a097397ee9bfbd54c0",
"1d67f7466fd711f8106fb437cb6a59b7ccd14cd6069edc132627a9fb01d4f09c",
"402450f5b4cd794d4198f940977bf4291ce25a7ff8b157adf71c07ed065db380",
"0173a5d24d393127d5e6fc043ff1a00dafc6a2777143cb98a803a0b6e8cd02c7",
"86150a141ebe5903a5d31e701698a01d598b81f099ea7577dad73033eab02ef9"
],
"time": 1296746959,
"mediantime": 1296746728,
"bits": 486604799,
"difficulty": 1,
"chainwork": "000000000000000000000000000000000000000000000000000001f701f701f7",
"previousblockhash": "00000000c7f50b6dfac8b8a59e11b7e62f07fdef20597089b9c5d64ebfe6d682",
"nextblockhash": "00000000f797111d0f67d7f08346757948e7c469f14cddbd1c3d0217306bf003"
}
```
Returns information about block.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | blockhash | Required | Hash of the block
2 | verbose | true | If set to false, it will return hex of the block
3 | details | false | If set to true, it will return transaction details too.
## getblockbyheight
```javascript
let blockhash, details, verbose;
```
```shell--vars
blockheight=502;
verbose=1;
details=0;
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "getblockbyheight",
"params": [ "'$blockheight'", "'$verbose'", "'$details'" ]
}'
```
```shell--cli
bcoin cli rpc getblockbyheight $blockheight $verbose $details
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('getblockbyheight', [ blockheight, verbose, details ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
{
"hash": "00000000e0290b7c66227c7499692aac5437860ee912424bf8eea3a3883a4e37",
"confirmations": 1177921,
"strippedsize": 2499,
"size": 2499,
"weight": 9996,
"height": 502,
"version": 1,
"versionHex": "00000001",
"merkleroot": "4f7a9087973b891fc86cc59fd9c2cb696f7a813360d3553626dc6c38909f9571",
"coinbase": "3337346bde777ade327922b5deef5fb7f88e98cecb22",
"tx": [
"2a69b021fc6cbd61260767302781c85fb0873acf18980ea6187fc868e4a3e3f9",
"c61f2ef26bb08dcf1e16db4fece56ac92a3acac24e4dac90315e5c0ad6af67e6",
"ed8c8213cc2d214ad2f293caae99e26e2c59d158f3eda5d9c1292e0961e20e76",
"21da008d1fddc1a067d2d6cd9bb6e78acb5bdc9560252c17cfd59c331dd5c2cf",
"90cc439e0a03109c33c966d92ccd18b0509ef678458d85a097397ee9bfbd54c0",
"1d67f7466fd711f8106fb437cb6a59b7ccd14cd6069edc132627a9fb01d4f09c",
"402450f5b4cd794d4198f940977bf4291ce25a7ff8b157adf71c07ed065db380",
"0173a5d24d393127d5e6fc043ff1a00dafc6a2777143cb98a803a0b6e8cd02c7",
"86150a141ebe5903a5d31e701698a01d598b81f099ea7577dad73033eab02ef9"
],
"time": 1296746959,
"mediantime": 1296746728,
"bits": 486604799,
"difficulty": 1,
"chainwork": "000000000000000000000000000000000000000000000000000001f701f701f7",
"previousblockhash": "00000000c7f50b6dfac8b8a59e11b7e62f07fdef20597089b9c5d64ebfe6d682",
"nextblockhash": "00000000f797111d0f67d7f08346757948e7c469f14cddbd1c3d0217306bf003"
}
```
Returns information about block by height.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | blockheight | Required | height of the block in the blockchain.
2 | verbose | true | If set to false, it will return hex of the block.
3 | details | false | If set to true, it will return transaction details too.
## getblockhash
```javascript
let blockheight;
```
```shell--vars
blockheight=502;
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "getblockhash",
"params": [ "'$blockheight'" ]
}'
```
```shell--cli
bcoin cli rpc getblockhash $blockheight
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('getblockhash', [ blockheight ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
"00000000e0290b7c66227c7499692aac5437860ee912424bf8eea3a3883a4e37"
```
Returns block's hash by height.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | blockheight | Required | height of the block in the blockchain.
## getblockheader
```javascript
let blockhash, verbose;
```
```shell--vars
blockhash='00000000e0290b7c66227c7499692aac5437860ee912424bf8eea3a3883a4e37';
verbose=1;
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "getblockheader",
"params": [ "'$blockhash'", "'$details'" ]
}'
```
```shell--cli
bcoin cli rpc getblockheader $blockhash $verbose
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('getblockheader', [ blockheight, verbose ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
{
"hash": "00000000e0290b7c66227c7499692aac5437860ee912424bf8eea3a3883a4e37",
"confirmations": 1177934,
"height": 502,
"version": 1,
"versionHex": "00000001",
"merkleroot": "4f7a9087973b891fc86cc59fd9c2cb696f7a813360d3553626dc6c38909f9571",
"time": 1296746959,
"mediantime": 1296746728,
"bits": 486604799,
"difficulty": 1,
"chainwork": "000000000000000000000000000000000000000000000000000001f701f701f7",
"previousblockhash": "00000000c7f50b6dfac8b8a59e11b7e62f07fdef20597089b9c5d64ebfe6d682",
"nextblockhash": "00000000f797111d0f67d7f08346757948e7c469f14cddbd1c3d0217306bf003"
}
```
Returns block's header by hash.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | blockheight | Required | height of the block in the blockchain.
2 | verbose | true | If set to false, it will return hex of the block.
## getchaintips
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "getchaintips"
}'
```
```shell--cli
bcoin cli rpc getchaintips
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('getchaintips');
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
Returns chaintips.
> The above command returns JSON "result" like this:
```json
[
{
"height": 1159071,
"hash": "0000000000043bc8896351bf4fbb9fadfa596566e6d88078a2364252346e0d2a",
"branchlen": 1,
"status": "valid-headers"
},
{
"height": 1158313,
"hash": "0000000000011e8328cf0382888e07f207e178e967f896794d600e39c962362e",
"branchlen": 1,
"status": "valid-headers"
},
...
]
```
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
None. |
## getdifficulty
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "getdifficulty"
}'
```
```shell--cli
bcoin cli rpc getdifficulty
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('getdifficulty');
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
1048576
```
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
None. |

144
api-docs-slate/source/includes/_node_rpc_chain.md

@ -0,0 +1,144 @@
# RPC Calls - Chain
## pruneblockchain
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "pruneblockchain",
"params": []
}'
```
```shell--cli
bcoin cli rpc pruneblockchain
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('pruneblockchain');
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
Prunes the blockchain, it will keep blocks specified in Network Configurations.
### Default Prune Options
Network | keepBlocks | pruneAfter
------- | ------- | -------
main | 288 | 1000
testnet | 10000 | 1000
regtest | 10000 | 1000
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
None. |
## invalidateblock
```javascript
let blockhash;
```
```shell--vars
blockhash='0000000000000dca8da883af9515dd90443d59139adbda3f9eeac1d18397fec3';
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "invalidateblock",
"params": [ "'$blockhash'" ]
}'
```
```shell--cli
bcoin cli rpc invalidateblock $blockhash
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('invalidateblock', [ blockhash ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
Invalidates the block in the chain.
It will rewind network to blockhash and invalidate it.
It won't accept that block as valid
*Invalidation will work while running, restarting node will remove invalid block from list.*
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | blockhash | Required | Block's hash
## reconsiderblock
```javascript
let blockhash;
```
```shell--vars
blockhash='0000000000000dca8da883af9515dd90443d59139adbda3f9eeac1d18397fec3';
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "reconsiderblock",
"params": [ "'$blockhash'" ]
}'
```
```shell--cli
bcoin cli rpc reconsiderblock $blockhash
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('reconsiderblock', [ blockhash ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
This rpc command will remove block from invalid block set.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | blockhash | Required | Block's hash

541
api-docs-slate/source/includes/_node_rpc_general.md

@ -0,0 +1,541 @@
## stop
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{ "method": "stop" }'
```
```shell--cli
bcoin cli rpc stop
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('stop');
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
"Stopping."
```
Stops the running node.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
None. |
## getinfo
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "getinfo",
"params": []
}'
```
```shell--cli
bcoin cli rpc getinfo
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('getinfo');
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
{
"version": "v1.0.0-beta.14",
"protocolversion": 70015,
"walletversion": 0,
"balance": 0,
"blocks": 1178980,
"timeoffset": 0,
"connections": 8,
"proxy": "",
"difficulty": 1048576,
"testnet": true,
"keypoololdest": 0,
"keypoolsize": 0,
"unlocked_until": 0,
"paytxfee": 0.0002,
"relayfee": 0.00001,
"errors": ""
}
```
Returns general info
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
None. |
## getmemoryinfo
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "getmemoryinfo",
"params": []
}'
```
```shell--cli
bcoin cli rpc getmemoryinfo
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('getmemoryinfo');
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
{
"total": 99,
"jsHeap": 19,
"jsHeapTotal": 29,
"nativeHeap": 69,
"external": 10
}
```
Returns Memory usage info.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
None. |
## setloglevel
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "setloglevel",
"params": [ "none" ]
}'
```
```shell--cli
bcoin cli rpc setloglevel none
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('setloglevel', [ 'none' ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
null
```
Change Log level of the running node.
Levels are: `NONE`, `ERROR`, `WARNING`, `INFO`, `DEBUG`, `SPAM`
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | level | Required | Level for the logger
## validateaddress
```javascript
let address;
```
```shell--vars
address='n34pHHSqsXJQwq9FXUsrfhmTghrVtN74yo';
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "validateaddress",
"params": [ "'$address'" ]
}'
```
```shell--cli
bcoin cli rpc validateaddress $address
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('validateaddress', [ address ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
{
"isvalid": true,
"address": "n34pHHSqsXJQwq9FXUsrfhmTghrVtN74yo",
"scriptPubKey": "76a914ec61435a3c8f0efee2ffafb8ddb4e1440d2db8d988ac",
"ismine": false,
"iswatchonly": false
}
```
Validates address.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | address | Required | Address to validate
## createmultisig
```javascript
let nrequired, pubkey0, pubkey1, pubkey2;
```
```shell--vars
nrequired=2;
pubkey0='02b3280e779a7c849f9d6460e926097fe4b0f6280fa6fd038ce8e1236a4688c358';
pubkey1='021f1dbc575db95a44e016fe6ecf00231109e7799d9b1e007dbe8814017cf0d65c';
pubkey2='0315613667e3ebe065c0b8d86ae0443d97de56545bdf38c99a6ee584f300206d9a';
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "createmultisig",
"params": [ "'$nrequired'", [ "'$pubkey0'", "'$pubkey1'", "'$pubkey2'" ] ]
}'
```
```shell--cli
bcoin cli rpc createmultisig $nrequired '[ "'$pubkey0'", "'$pubkey1'", "'$pubkey2'" ]'
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('createmultisig', [ nrequired, [ pubkey0, pubkey1, pubkey2 ] ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
{
"address": "2MzY9R5P1Wfy9aNdqyoH63K1EQZF7APuZ4S",
"redeemScript": "5221021f1dbc575db95a44e016fe6ecf00231109e7799d9b1e007dbe8814017cf0d65c2102b3280e779a7c849f9d6460e926097fe4b0f6280fa6fd038ce8e1236a4688c358210315613667e3ebe065c0b8d86ae0443d97de56545bdf38c99a6ee584f300206d9a53ae"
}
```
create multisig address
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | nrequired | Required | Required number of approvals for spending
2 | keyArray | Required | Array of public keys
## createwitnessaddress
```javascript
let script;
```
```shell--vars
script='5221021f1dbc575db95a44e016fe6ecf00231109e7799d9b1e007dbe8814017cf0d65c2102b3280e779a7c849f9d6460e926097fe4b0f6280fa6fd038ce8e1236a4688c358210315613667e3ebe065c0b8d86ae0443d97de56545bdf38c99a6ee584f300206d9a53ae';
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "createwitnessaddress",
"params": [ "'$script'" ]
}'
```
```shell--cli
bcoin cli rpc createwitnessaddress $script
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('createwitnessaddress', [ script ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
{
"address": "tb1qlfgqame3n0dt2ldjl2m9qjg6n2vut26jw3ezm25hqx9ez4m9wp5q567kg2",
"witnessScript": "0020fa500eef319bdab57db2fab650491a9a99c5ab5274722daa97018b9157657068"
}
```
Creates witness address.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | script | Required | Bitcoin script.
## signmessagewithprivkey
```javascript
let privkey, message;
```
```shell--vars
privkey='EL4QU6ViZvT4RuCTCivw2uBnvBPSamP5jMtH31gGQLbEEcmNCHVz';
message='hello';
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "signmessagewithprivkey",
"params": [ "'$privkey'", "'$message'"]
}'
```
```shell--cli
bcoin cli rpc signmessagewithprivkey $privkey $message
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('signmessagewithprivkey', [ privkey, message ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
"MEQCIAwF9NPMo5KBRsCWTBJ2r69/h7CfDl+RQfxxwAbNp1WJAiAiubiK5rg9MugiU7EHpwbJLc3b356LAedob0ePI40Wmg=="
```
Signs message with private key.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | privkey | Required | Private key
1 | message | Required | Message you want to sign.
## verifymessage
```javascript
let address, signature, message;
```
```shell--vars
address='R9LTC6Sp6Zwk71qUrm81sEdsppFNiDM6mF';
signature='MEQCIAwF9NPMo5KBRsCWTBJ2r69/h7CfDl+RQfxxwAbNp1WJAiAiubiK5rg9MugiU7EHpwbJLc3b356LAedob0ePI40Wmg==';
message='hello';
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "verifymessage",
"params": [ "'$address'", "'$signature'", "'$message'" ]
}'
```
```shell--cli
bcoin cli rpc verifymessage $address $signature $message
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('verifymessage', [ address, signature, message ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
true
```
Verify sign
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | address | Required | Address of the signer
2 | signature | Required | Signature of signed message
3 | message | Required | Message that was signed
## setmocktime
```javascript
let timestamp;
```
```shell--vars
timestamp=1503058155;
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "setmocktime",
"params": [ '$timestamp' ]
}'
```
```shell--cli
bcoin cli rpc setmocktime $timestamp
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('setmocktime', [ timestamp ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
null
```
Changes network time (This is consensus-critical)
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | timestamp | Required | timestamp to change to

651
api-docs-slate/source/includes/_node_rpc_mempool.md

@ -0,0 +1,651 @@
# RPC Calls - Mempool
## getmempoolinfo
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "getmempoolinfo"
}'
```
```shell--cli
bcoin cli rpc getmempoolinfo
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('getmempoolinfo');
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
{
"size": 20,
"bytes": 68064,
"usage": 68064,
"maxmempool": 100000000,
"mempoolminfee": 0.00001
}
```
Returns informations about mempool.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
None. |
## getmempoolancestors
```javascript
let txhash, verbose;
```
```shell--vars
txhash='939a3b8485b53a718d89e7e4412473b3762fa1d9bbd555fc8b01e73be0ab1881';
verbose=1;
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "getmempoolancestors",
"params": [ "'$txhash'", "'$verbose'" ]
}'
```
```shell--cli
bcoin cli rpc getmempoolancestors $txhash $verbose
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('getmempoolancestors', [ txhash, verbose ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
// verbose=1
[
{
"size": 225,
"fee": 0.0000454,
"modifiedfee": 0,
"time": 1502891340,
"height": 201,
"startingpriority": 0,
"currentpriority": 0,
"descendantcount": 1,
"descendantsize": 451,
"descendantfees": 9080,
"ancestorcount": 0,
"ancestorsize": 0,
"ancestorfees": 0,
"depends": []
}
]
```
```json
// verbose=0
[
"56ab7663c80cb6ffc9f8a4b493d77b2e6f52ae8ff64eefa8899c2065922665c8"
]
```
returns all in-mempool ancestors for a transaction in the mempool.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | txhash | Required | Transaction Hash
2 | verbose | false | False returns only tx hashs, true - returns dependency tx info
## getmempooldescendants
```javascript
let txhash, verbose;
```
```shell--vars
txhash='56ab7663c80cb6ffc9f8a4b493d77b2e6f52ae8ff64eefa8899c2065922665c8';
verbose=1;
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "getmempooldescendants",
"params": [ "'$txhash'", "'$verbose'" ]
}'
```
```shell--cli
bcoin cli rpc getmempooldescendants $txhash $verbose
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('getmempooldescendants', [ txhash, verbose ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
// verbose=1
[
{
"size": 226,
"fee": 0.0000454,
"modifiedfee": 0,
"time": 1502891378,
"height": 201,
"startingpriority": 0,
"currentpriority": 0,
"descendantcount": 0,
"descendantsize": 226,
"descendantfees": 4540,
"ancestorcount": 1,
"ancestorsize": 0,
"ancestorfees": 0,
"depends": [
"56ab7663c80cb6ffc9f8a4b493d77b2e6f52ae8ff64eefa8899c2065922665c8"
]
}
]
```
```json
// verbose=0
[
"939a3b8485b53a718d89e7e4412473b3762fa1d9bbd555fc8b01e73be0ab1881"
]
```
returns all in-mempool descendants for a transaction in the mempool.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | txhash | Required | Transaction hash
2 | verbose | false | False returns only tx hashs, true - returns dependency tx info
## getmempoolentry
```javascript
let txhash;
```
```shell--vars
txhash='939a3b8485b53a718d89e7e4412473b3762fa1d9bbd555fc8b01e73be0ab1881';
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "getmempoolentry",
"params": [ "'$txhash'" ]
}'
```
```shell--cli
bcoin cli rpc getmempoolentry $txhash
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('getmempoolentry', [ txhash ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
{
"size": 226,
"fee": 0.0000454,
"modifiedfee": 0,
"time": 1502891378,
"height": 201,
"startingpriority": 0,
"currentpriority": 0,
"descendantcount": 0,
"descendantsize": 226,
"descendantfees": 4540,
"ancestorcount": 1,
"ancestorsize": 0,
"ancestorfees": 0,
"depends": [
"56ab7663c80cb6ffc9f8a4b493d77b2e6f52ae8ff64eefa8899c2065922665c8"
]
}
```
returns mempool transaction info by its hash.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | txhash | Required | Transaction Hash
## getrawmempool
```javascript
let verbose;
```
```shell--vars
verbose=1;
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "getrawmempool",
"params": [ "'$verbose'" ]
}'
```
```shell--cli
bcoin cli rpc getrawmempool $verbose
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('getrawmempool', [ verbose ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
{
"56ab7663c80cb6ffc9f8a4b493d77b2e6f52ae8ff64eefa8899c2065922665c8": {
"size": 225,
"fee": 0.0000454,
"modifiedfee": 0,
"time": 1502891340,
"height": 201,
"startingpriority": 0,
"currentpriority": 0,
"descendantcount": 1,
"descendantsize": 451,
"descendantfees": 9080,
"ancestorcount": 0,
"ancestorsize": 0,
"ancestorfees": 0,
"depends": []
},
"939a3b8485b53a718d89e7e4412473b3762fa1d9bbd555fc8b01e73be0ab1881": {
"size": 226,
"fee": 0.0000454,
"modifiedfee": 0,
"time": 1502891378,
"height": 201,
"startingpriority": 0,
"currentpriority": 0,
"descendantcount": 0,
"descendantsize": 226,
"descendantfees": 4540,
"ancestorcount": 1,
"ancestorsize": 0,
"ancestorfees": 0,
"depends": [
"56ab7663c80cb6ffc9f8a4b493d77b2e6f52ae8ff64eefa8899c2065922665c8"
]
}
}
```
Returns mempool detailed information (on verbose).
Or mempool tx list.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | verbose | false | False returns only tx hashs, true - returns full tx info
## prioritisetransaction
```javascript
let txhash, priorityDelta, feeDelta;
```
```shell--vars
txhash='';
priorityDelta=1000;
feeDelta=1000;
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "prioritisetransaction",
"params": [ "'$txhash'", "'$priorityDelta'", "'$feeDelta'" ]
}'
```
```shell--cli
bcoin cli rpc prioritisetransaction $txhash $priorityDelta $feeDelta
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('prioritisetransaction', [ txhash, priorityDelta, feeDelta ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
true
```
Prioritises the transaction.
*Note: changing fee or priority will only trick local miner (using this mempool)
into accepting Transaction(s) into the block. (even if Priority/Fee doen't qualify)*
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | txid | Required | Transaction hash
2 | priority delta | Required | Virtual priority to add/subtract to the entry
3 | fee delta | Required | Virtual fee to add/subtract to the entry
## estimatefee
```javascript
let nblocks;
```
```shell--vars
nblocks=10;
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "estimatefee",
"params": [ "'$nblocks'" ]
}'
```
```shell--cli
bcoin cli rpc estimatefee $nblocks
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('estimatefee', [ nblocks ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
0.001
```
Estimates fee to be paid for transaction.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | nblocks | 1 | Number of blocks to check for estimation.
## estimatepriority
```javascript
let nblocks;
```
```shell--vars
nblocks=10;
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "estimatepriority",
"params": [ "'$nblocks'" ]
}'
```
```shell--cli
bcoin cli rpc estimatepriority $nblocks
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('estimatepriority', [ nblocks ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
718158904.3501
```
estimates the priority (coin age) that a transaction needs in order to be included within a certain number of blocks as a free high-priority transaction.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | nblocks | 1 | Number of blocks to check for estimation.
## estimatesmartfee
```javascript
let nblocks;
```
```shell--vars
nblocks=10;
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "estimatesmartfee",
"params": [ "'$nblocks'" ]
}'
```
```shell--cli
bcoin cli rpc estimatesmartfee $nblocks
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('estimatesmartfee', [ nblocks ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
{
"fee": 0.001,
"blocks": 10
}
```
Estimates smart fee to be paid for transaction.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | nblocks | 1 | Number of blocks to check for estimation.
## estimatesmartpriority
```javascript
let nblocks;
```
```shell--vars
nblocks=10;
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "estimatesmartpriority",
"params": [ "'$nblocks'" ]
}'
```
```shell--cli
bcoin cli rpc estimatesmartpriority $nblocks
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('estimatesmartpriority', [ nblocks ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
{
"priority": 718158904.3501,
"blocks": 10
}
```
estimates smart priority (coin age) that a transaction needs in order to be included within a certain number of blocks as a free high-priority transaction.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | nblocks | 1 | Number of blocks to check for estimation.

638
api-docs-slate/source/includes/_node_rpc_mining.md

File diff suppressed because one or more lines are too long

614
api-docs-slate/source/includes/_node_rpc_network.md

@ -0,0 +1,614 @@
# RPC Calls - Network
## getconnectioncount
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "getconnectioncount",
"params": []
}'
```
```shell--cli
bcoin cli rpc getconnectioncount
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('getconnectioncount');
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
8
```
Returns connection count.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
None. |
## ping
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "ping",
"params": []
}'
```
```shell--cli
bcoin cli rpc ping
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('ping');
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
null
```
Will send ping request to every connected peer.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
None. |
## getpeerinfo
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "getpeerinfo",
"params": []
}'
```
```shell--cli
bcoin cli rpc getpeerinfo
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('getpeerinfo');
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
[
{
"id": 1,
"addr": "198.51.100.82:18333",
"addrlocal": "203.0.113.114:60760",
"services": "0000000d",
"relaytxes": true,
"lastsend": 1503257171,
"lastrecv": 1503257171,
"bytessent": 1962,
"bytesrecv": 32499,
"conntime": 121,
"timeoffset": -1,
"pingtime": 0.143,
"minping": 0.143,
"version": 70015,
"subver": "/Satoshi:0.14.1/",
"inbound": false,
"startingheight": 1179570,
"besthash": null,
"bestheight": -1,
"banscore": 0,
"inflight": [],
"whitelisted": false
},
...
]
```
Returns information about all connected peers.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
None. |
## addnode
```javascript
let nodeAddr, cmd;
```
```shell--vars
nodeAddr='198.51.100.82:18333';
cmd='add'
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "addnode",
"params": [ "'$nodeAddr'", "'$cmd'" ]
}'
```
```shell--cli
bcoin cli rpc addnode $nodeAddr $cmd
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('addnode', [ nodeAddr, cmd ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
null
```
Adds or removes peers in Host List.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | addr | Required | IP Address of the Node.
2 | cmd | Required | Command
### Commands
Command | Description
---- | ----
add | Adds node to Host List and connects to it
onetry | Tries to connect to the given node
remove | Removes node from host list
## disconnectnode
```javascript
let nodeAddr;
```
```shell--vars
nodeAddr='198.51.100.82:18333';
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "disconnectnode",
"params": [ "'$nodeAddr'" ]
}'
```
```shell--cli
bcoin cli rpc disconnectnode $nodeAddr
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('disconnectnode', [ nodeAddr ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
null
```
Disconnects node.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | addr | Required | IP Address of the Node.
## getaddednodeinfo
```javascript
let nodeAddr;
```
```shell--vars
nodeAddr='198.51.100.82:18333';
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "getaddednodeinfo",
"params": [ "'$nodeAddr'" ]
}'
```
```shell--cli
bcoin cli rpc getaddednodeinfo $nodeAddr
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('getaddednodeinfo', [ nodeAddr ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
[
{
"addednode": "198.51.100.82:18333",
"connected": true,
"addresses": [
{
"address": "198.51.100.82:18333",
"connected": "outbound"
}
]
}
]
```
Returns node information from host list.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | addr | Required | IP Address of the Node.
## getnettotals
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "getnettotals",
"params": []
}'
```
```shell--cli
bcoin cli rpc getnettotals
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('getnettotals');
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
{
"totalbytesrecv": 370598,
"totalbytessent": 110058,
"timemillis": 1503262547279
}
```
Returns information about used network resources.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
None. |
## getnetworkinfo
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "getnetworkinfo",
"params": []
}'
```
```shell--cli
bcoin cli rpc getnetworkinfo
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('getnetworkinfo');
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
{
"version": "v1.0.0-beta.14",
"subversion": "/bcoin:v1.0.0-beta.14/",
"protocolversion": 70015,
"localservices": "00000009",
"localrelay": true,
"timeoffset": -1,
"networkactive": true,
"connections": 8,
"networks": [],
"relayfee": 0.00001,
"incrementalfee": 0,
"localaddresses": [
{
"address": "203.0.113.114",
"port": 18333,
"score": 3
}
],
"warnings": ""
}
```
Returns local node's network information
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
None. |
## setban
```javascript
let nodeAddr, cmd;
```
```shell--vars
nodeAddr='198.51.100.82:18333';
cmd='add'
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "setban",
"params": [ "'$nodeAddr'", "'$cmd'" ]
}'
```
```shell--cli
bcoin cli rpc setban $nodeAddr $cmd
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('setban', [ nodeAddr, cmd ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
null
```
Adds or removes nodes from banlist.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | addr | Required | IP Address of the Node.
2 | cmd | Required | Command
### Commands
Command | Description
---- | ----
add | Adds node to ban list, removes from host list, disconnects.
remove | Removes node from ban list
## listbanned
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "listbanned",
"params": []
}'
```
```shell--cli
bcoin cli rpc listbanned
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('listbanned');
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
[
{
"address": "198.51.100.82:18333",
"banned_until": 1503349501,
"ban_created": 1503263101,
"ban_reason": ""
},
...
]
```
Lists all banned peers.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
None. |
## clearbanned
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "clearbanned",
"params": []
}'
```
```shell--cli
bcoin cli rpc clearbanned
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('clearbanned');
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
null
```
Removes all banned peers.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
None. |

680
api-docs-slate/source/includes/_node_rpc_tx.md

@ -0,0 +1,680 @@
# RPC Calls - Transactions
## gettxout
```javascript
let txhash, index, includemempool;
```
```shell--vars
txhash='28d65fdaf5334ffd29066d7076f056bb112baa4bb0842f6eaa06171c277b4e8c';
index=0;
includemempool=1;
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "gettxout",
"params": [ "'$txhash'", "'$index'", "'$includemempool'" ]
}'
```
```shell--cli
bcoin cli rpc gettxout $txhash $index $includemempool
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('gettxout', [ txhash, index, includemempool ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
{
"bestblock": "00000000000004f0fbf1b2290e8255bbd468640d747fd9d44a16e77d9e129a55",
"confirmations": 1,
"value": 1.01,
"scriptPubKey": {
"asm": "OP_HASH160 6a58967510cfd7e04987b245f73dbf62e8d3fdf8 OP_EQUAL",
"hex": "a9146a58967510cfd7e04987b245f73dbf62e8d3fdf887",
"type": "SCRIPTHASH",
"reqSigs": 1,
"addresses": [
"2N2wXjoQbEQTKQuqYdkpHMp7rPpnpumYYqe"
]
},
"version": 1,
"coinbase": false
}
```
Get outpoint of the transaction.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | txid | Required | Transaction hash
2 | index | Required | Index of the Outpoint tx.
3 | includemempool | true | Whether to include mempool transactions.
## gettxoutsetinfo
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "gettxoutsetinfo",
"params": []
}'
```
```shell--cli
bcoin cli rpc gettxoutsetinfo
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('gettxoutsetinfo');
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
{
"height": 1178729,
"bestblock": "00000000000004f0fbf1b2290e8255bbd468640d747fd9d44a16e77d9e129a55",
"transactions": 14827318,
"txouts": 17644185,
"bytes_serialized": 0,
"hash_serialized": 0,
"total_amount": 20544080.67292757
}
```
Returns information about UTXO's from Chain.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
None. |
## getrawtransaction
```javascript
let txhash, verbose=0;
```
```shell--vars
txhash='28d65fdaf5334ffd29066d7076f056bb112baa4bb0842f6eaa06171c277b4e8c';
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "getrawtransaction",
"params": [ "'$txhash'", "'$verbose'" ]
}'
```
```shell--cli
bcoin cli rpc getrawtransaction $txhash $verbose
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('getrawtransaction', [ txhash, verbose ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
"0100000002500310ff36beb6c3608230534ef995f7751b6f948aeea8d21d5cc9dd5023a2c4010000006b483045022100e7c71d397b687f9f30e6003ceedc4c50436fdb2329b7a8a36c9c6759077969d30220059f24e917260d3e601c77079d03c9e73d04fd85f625eaebfd14a1ff695a72230121020bc134c91f4ff068f3a970616fad577f949406c18849321a2f6d4df96fc56c77feffffffeffed95ded4f227fc6717f224e85e50348ce0198303a5418f157ade42828a1e3000000006b483045022100f0bde463404db0983e0f221bfa1b13edf1063a78e869295c9457864b122a622b02207d9d5df76ecac6289784201e9a918acb34510c2d65144bf8e4753a3413024e320121022565ed0ff8f79ecf11e8f33b9fbba5606dbc0618813acd74603f9466e88fb8a8feffffff02402305060000000017a9146a58967510cfd7e04987b245f73dbf62e8d3fdf8871e194f00000000001976a914132b05f47f2b1b56f26a78d3962e3acd0735f12d88ac00000000"
```
Returns raw transaction
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | txhash | Required | Transaction hash
2 | verbose | false | Returns json formatted if true
## decoderawtransaction
```javascript
let rawtx;
```
```shell--vars
rawtx='0100000002500310ff36beb6c3608230534ef995f7751b6f948aeea8d21d5cc9dd5023a2c4010000006b483045022100e7c71d397b687f9f30e6003ceedc4c50436fdb2329b7a8a36c9c6759077969d30220059f24e917260d3e601c77079d03c9e73d04fd85f625eaebfd14a1ff695a72230121020bc134c91f4ff068f3a970616fad577f949406c18849321a2f6d4df96fc56c77feffffffeffed95ded4f227fc6717f224e85e50348ce0198303a5418f157ade42828a1e3000000006b483045022100f0bde463404db0983e0f221bfa1b13edf1063a78e869295c9457864b122a622b02207d9d5df76ecac6289784201e9a918acb34510c2d65144bf8e4753a3413024e320121022565ed0ff8f79ecf11e8f33b9fbba5606dbc0618813acd74603f9466e88fb8a8feffffff02402305060000000017a9146a58967510cfd7e04987b245f73dbf62e8d3fdf8871e194f00000000001976a914132b05f47f2b1b56f26a78d3962e3acd0735f12d88ac00000000';
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "decoderawtransaction",
"params": [ "'$rawtx'" ]
}'
```
```shell--cli
bcoin cli rpc decoderawtransaction $rawtx
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('decoderawtransaction', [ rawtx ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
{
"txid": "28d65fdaf5334ffd29066d7076f056bb112baa4bb0842f6eaa06171c277b4e8c",
"hash": "28d65fdaf5334ffd29066d7076f056bb112baa4bb0842f6eaa06171c277b4e8c",
"size": 372,
"vsize": 372,
"version": 1,
"locktime": 0,
"vin": [
{
"txid": "c4a22350ddc95c1dd2a8ee8a946f1b75f795f94e53308260c3b6be36ff100350",
"scriptSig": {
"asm": "3045022100e7c71d397b687f9f30e6003ceedc4c50436fdb2329b7a8a36c9c6759077969d30220059f24e917260d3e601c77079d03c9e73d04fd85f625eaebfd14a1ff695a722301 020bc134c91f4ff068f3a970616fad577f949406c18849321a2f6d4df96fc56c77",
"hex": "483045022100e7c71d397b687f9f30e6003ceedc4c50436fdb2329b7a8a36c9c6759077969d30220059f24e917260d3e601c77079d03c9e73d04fd85f625eaebfd14a1ff695a72230121020bc134c91f4ff068f3a970616fad577f949406c18849321a2f6d4df96fc56c77"
},
"sequence": 4294967294,
"vout": 1
},
{
"txid": "e3a12828e4ad57f118543a309801ce4803e5854e227f71c67f224fed5dd9feef",
"scriptSig": {
"asm": "3045022100f0bde463404db0983e0f221bfa1b13edf1063a78e869295c9457864b122a622b02207d9d5df76ecac6289784201e9a918acb34510c2d65144bf8e4753a3413024e3201 022565ed0ff8f79ecf11e8f33b9fbba5606dbc0618813acd74603f9466e88fb8a8",
"hex": "483045022100f0bde463404db0983e0f221bfa1b13edf1063a78e869295c9457864b122a622b02207d9d5df76ecac6289784201e9a918acb34510c2d65144bf8e4753a3413024e320121022565ed0ff8f79ecf11e8f33b9fbba5606dbc0618813acd74603f9466e88fb8a8"
},
"sequence": 4294967294,
"vout": 0
}
],
"vout": [
{
"value": 1.01,
"n": 0,
"scriptPubKey": {
"asm": "OP_HASH160 6a58967510cfd7e04987b245f73dbf62e8d3fdf8 OP_EQUAL",
"hex": "a9146a58967510cfd7e04987b245f73dbf62e8d3fdf887",
"type": "SCRIPTHASH",
"reqSigs": 1,
"addresses": [
"2N2wXjoQbEQTKQuqYdkpHMp7rPpnpumYYqe"
]
}
},
{
"value": 0.05183774,
"n": 1,
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 132b05f47f2b1b56f26a78d3962e3acd0735f12d OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a914132b05f47f2b1b56f26a78d3962e3acd0735f12d88ac",
"type": "PUBKEYHASH",
"reqSigs": 1,
"addresses": [
"mhGJg1PJg8hVPX9A6zg4q389YFisSzQW6d"
]
}
}
],
"blockhash": null,
"confirmations": 0,
"time": 0,
"blocktime": 0
}
```
Decodes raw tx and provide chain info.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | rawtx | Required | Raw transaction hex
## decodescript
```javascript
let script;
```
```shell--vars
script='483045022100f0bde463404db0983e0f221bfa1b13edf1063a78e869295c9457864b122a622b02207d9d5df76ecac6289784201e9a918acb34510c2d65144bf8e4753a3413024e320121022565ed0ff8f79ecf11e8f33b9fbba5606dbc0618813acd74603f9466e88fb8a8';
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "decodescript",
"params": [ "'$script'" ]
}'
```
```shell--cli
bcoin cli rpc decodescript $script
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('decodescript', [ script ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
{
"asm": "3045022100f0bde463404db0983e0f221bfa1b13edf1063a78e869295c9457864b122a622b02207d9d5df76ecac6289784201e9a918acb34510c2d65144bf8e4753a3413024e3201 022565ed0ff8f79ecf11e8f33b9fbba5606dbc0618813acd74603f9466e88fb8a8",
"type": "NONSTANDARD",
"reqSigs": 1,
"addresses": [],
"p2sh": "2MyVRHsEpec67MkPLGr4NR2bT1ZFuzFGUoB"
}
```
Decodes script
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | script | Required | Script hex
## sendrawtransaction
```javascript
let rawtx;
```
```shell--vars
rawtx='0100000002500310ff36beb6c3608230534ef995f7751b6f948aeea8d21d5cc9dd5023a2c4010000006b483045022100e7c71d397b687f9f30e6003ceedc4c50436fdb2329b7a8a36c9c6759077969d30220059f24e917260d3e601c77079d03c9e73d04fd85f625eaebfd14a1ff695a72230121020bc134c91f4ff068f3a970616fad577f949406c18849321a2f6d4df96fc56c77feffffffeffed95ded4f227fc6717f224e85e50348ce0198303a5418f157ade42828a1e3000000006b483045022100f0bde463404db0983e0f221bfa1b13edf1063a78e869295c9457864b122a622b02207d9d5df76ecac6289784201e9a918acb34510c2d65144bf8e4753a3413024e320121022565ed0ff8f79ecf11e8f33b9fbba5606dbc0618813acd74603f9466e88fb8a8feffffff02402305060000000017a9146a58967510cfd7e04987b245f73dbf62e8d3fdf8871e194f00000000001976a914132b05f47f2b1b56f26a78d3962e3acd0735f12d88ac00000000';
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "sendrawtransaction",
"params": [ "'$rawtx'" ]
}'
```
```shell--cli
bcoin cli rpc sendrawtransaction $rawtx
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('sendrawtransaction', [ rawtx ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
>
```json
"28d65fdaf5334ffd29066d7076f056bb112baa4bb0842f6eaa06171c277b4e8c"
```
Sends raw transaction without verification
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | rawtx | Required | Raw transaction hex
## createrawtransaction
```javascript
let txhash, txindex, amount, address, data;
```
```shell--vars
txhash='d1e1b6a8ff8c4d2ade2113a5dd250637e5f99667d36dcae9b70139516cb7052f';
txindex=1;
amount=1;
address='RStiqGLWA3aSMrWDyJvur4287GQ81AtLh1';
data='';
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "createrawtransaction",
"params": [
[{ "txid": "'$txhash'", "vout": "'$txindex'" }],
{ "'$address'": "'$amount'", "data": "'$data'" }
]
}'
```
```shell--cli
bcoin cli rpc createrawtransaction \
'[{ "txid": "'$txhash'", "vout": "'$txindex'" }]' \
'{ "'$address'": "'$amount'", "data": "'$data'" }'
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'regtest'
});
(async () => {
const sendTo = {
data: data
};
sendTo[address] = amount;
const res = await rpc.execute('createrawtransaction', [ [{ txid: txhash, vout: txindex }], sendTo]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
"01000000012f05b76c513901b7e9ca6dd36796f9e5370625dda51321de2a4d8cffa8b6e1d10100000000ffffffff0200e1f505000000001976a914c1325e8fb60bd71d23532c39b4c9e743a2cc764988ac0000000000000000026a0000000000"
```
<aside class="info">
Note: Transaction in example doesn't specify change output,
you can do it by specifying another <code>address: amount</code> pair.
</aside>
Creates raw, unsigned transaction without any formal verification.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | outpoints | Required | Outpoint list
1.1 | txid | | Transaction Hash
1.2 | vout | | Transaction Outpoint Index
1.3 | sequence | | Sequence number for input
2 | sendto | Required | List of addresses with amounts that we are sending to.
2.1 | address | 0 | `address: amount` key pairs
2.2 | data | nullData | Data output
3 | locktime | | earliest time a transaction can be added
## signrawtransaction
```javascript
let rawtx, txhash, txindex, scriptPubKey, amount, privkey;
```
```shell--vars
rawtx='01000000012f05b76c513901b7e9ca6dd36796f9e5370625dda51321de2a4d8cffa8b6e1d10100000000ffffffff020000000000000000026a0000e1f505000000001976a914c1325e8fb60bd71d23532c39b4c9e743a2cc764988ac00000000';
txhash='d1e1b6a8ff8c4d2ade2113a5dd250637e5f99667d36dcae9b70139516cb7052f';
txindex=1;
scriptPubKey='76a9146efd5e2fda72ae2e37f8fb8cde83fbc8025fc96e88ac';
amount=1;
privkey='ET4VkeCoHmtKtoWJKco5PBSaVkqsVwqSbsqhneqN4Uo5yaTMxRmV';
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "signrawtransaction",
"params": [
"'$rawtx'",
[{
"txid": "'$txhash'",
"vout": "'$txindex'",
"scriptPubKey": "'$scriptPubKey'",
"amount": "'$amount'"
}],
[ "'$privkey'" ]
]
}'
```
```shell--cli
bcoin cli rpc signrawtransaction $rawtx \
'[{ "txid": "'$txhash'", "vout": "'$txindex'", "scriptPubKey": "'$scriptPubKey'", "amount": "'$amount'" }]' \
'[ "'$privkey'" ]'
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'regtest'
});
(async () => {
const res = await rpc.execute('signrawtransaction', [ rawtx,
[{
txid: txhash,
vout: txindex,
scriptPubKey: scriptPubKey,
amount: amount
}],
[ privkey ]
]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
{
"hex": "01000000012f05b76c513901b7e9ca6dd36796f9e5370625dda51321de2a4d8cffa8b6e1d1010000006b48304502210094252b4db106def63264668717c5ad66e2804c5e1b390c6240e82515fb0c12690220708430b14ceb0a15308e665de21cb3eb9e6cd9e4571e110fbfddf65ef702cd990121035ef2bf6d09a343c4c0be6fb5b489b217c00f477a9878b60ca3ceca4c2b052c3cffffffff020000000000000000026a0000e1f505000000001976a914c1325e8fb60bd71d23532c39b4c9e743a2cc764988ac00000000",
"complete": true
}
```
Signs raw transaction
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | rawtx | Required | raw tx
2 | inputs | Required | Coins you're going to spend
2.1 | txid | | Transaction Hash
2.2 | vout | | Transaction Outpoint Index
2.3 | scriptPubKey | | script with pubkey you are going to sign
2.4 | redeemScript | | redeemScript if tx is P2SH
3 | privkeylist | | List of private keys
4 | sighashtype | | Type of signature hash
## gettxoutproof
```javascript
let txhash;
```
```shell--vars
txhash='c75f8c12c6d0d1a16d7361b724898968c71de0335993ee589f82fda8ac482bfc';
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "gettxoutproof",
"params": [ "'$txhash'" ]
}'
```
```shell--cli
bcoin cli rpc gettxoutproof $txhash
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('gettxoutproof', [ txhash ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
"000000208c13da491196839dd019c4ae0564f351502a4951e11b4302454b020000000000f1788fd057d657150b12e5638c7348fb55fdcda4ff4ddb1d1503de3576de6a4cbe22db58f0ec091b918981c50200000001f1788fd057d657150b12e5638c7348fb55fdcda4ff4ddb1d1503de3576de6a4c0100"
```
Checks if transactions are within block.
Returns raw block.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | txidlist | Required | array of transaction hashes
2 | blockhash | Based on TX | Block hash
## verifytxoutproof
```javascript
let proof;
```
```shell--vars
proof='000000208c13da491196839dd019c4ae0564f351502a4951e11b4302454b020000000000f1788fd057d657150b12e5638c7348fb55fdcda4ff4ddb1d1503de3576de6a4cbe22db58f0ec091b918981c50200000001f1788fd057d657150b12e5638c7348fb55fdcda4ff4ddb1d1503de3576de6a4c0100';
```
```shell--curl
curl $url/ \
-H 'Content-Type: application/json' \
-X POST \
--data '{
"method": "verifytxoutproof",
"params": [ "'$proof'" ]
}'
```
```shell--cli
bcoin cli rpc verifytxoutproof $proof
```
```javascript
const rpc = new bcoin.http.RPCClient({
network: 'testnet'
});
(async () => {
const res = await rpc.execute('verifytxoutproof', [ proof ]);
console.log(res);
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON "result" like this:
```json
[]
```
Checks the proof for transaction inclusion.
### Params
N. | Name | Default | Description
--------- | --------- | --------- | -----------
1 | proof | Required | Proof of transaction inclusion.

336
api-docs-slate/source/includes/_transaction.md

@ -0,0 +1,336 @@
# Transaction
Getting transaction information via APi.
<aside class="info">
You need to enable <code>index-tx</code> and <code>index-address</code> in order
to lookup transactions by transaction hashes and addresses, respectively.
</aside>
## Get tx by txhash
```javascript
let txhash;
```
```shell--vars
txhash='86150a141ebe5903a5d31e701698a01d598b81f099ea7577dad73033eab02ef9';
```
```shell--curl
curl $url/tx/$txhash
```
```shell--cli
bcoin cli tx $txhash
```
```javascript
const client = new bcoin.http.Client({
network: 'testnet'
});
(async () => {
await client.open();
const tx = await client.getTX(txhash);
console.log(tx);
await client.close();
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON structured like this:
```json
{
"hash": "86150a141ebe5903a5d31e701698a01d598b81f099ea7577dad73033eab02ef9",
"witnessHash": "86150a141ebe5903a5d31e701698a01d598b81f099ea7577dad73033eab02ef9",
"fee": 50000,
"rate": 220264,
"mtime": 1501093478,
"height": 502,
"block": "00000000e0290b7c66227c7499692aac5437860ee912424bf8eea3a3883a4e37",
"time": 1296746959,
"index": 8,
"version": 1,
"flag": 1,
"inputs": [
{
"prevout": {
"hash": "0173a5d24d393127d5e6fc043ff1a00dafc6a2777143cb98a803a0b6e8cd02c7",
"index": 0
},
"script": "493046022100be75ae6dbf9eab7656562136511501c83918ca28c5f96565ca1960b3dbb581b6022100d15692af456e8721fddeeb0d6df5d8a147afd8a3b2a39bbceae9b1bdfd53ade20121038e297cf2cf71c16592c36ca48f5b2a5bbb73e776e772079f4c695b12eec1a509",
"witness": "00",
"sequence": 4294967295,
"coin": {
"version": 1,
"height": 502,
"value": 4824247882,
"script": "76a914bc7aad9746a0bc03ed9715f13c94e554df90b84688ac",
"address": "mxhYHwYZdYh1AkLsUbEmU9ZGdvLfoNRdD6",
"coinbase": false
}
}
],
"outputs": [
{
"value": 4823922491,
"script": "76a914682215dfa6912d88f55a1853414d516122fcc66988ac",
"address": "mq1ZQJW1qPeNPNL83mpAWfNFPW9qwGDR2K"
},
{
"value": 275391,
"script": "76a914edb1dfaf6e0b39449da811275386edf2eb54baba88ac",
"address": "n3BmXQPa1dKi3zEyCdCGNHTuE5GLdmw1Tr"
}
],
"locktime": 0
}
```
### HTTP Request
`GET /tx/:txhash`
### URL Parameters
Parameter | Description
--------- | -----------
:txhash | Hash of tx.
## Get tx by address
```javascript
let address;
```
```shell--vars
address='n3BmXQPa1dKi3zEyCdCGNHTuE5GLdmw1Tr';
```
```shell--curl
curl $url/tx/address/$address
```
```shell--cli
bcoin cli tx $address
```
```javascript
const client = new bcoin.http.Client({
network: 'testnet'
});
(async () => {
await client.open();
const txs = await client.getTXByAddress(address);
console.log(txs);
await client.close();
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON structured like this:
```json
[
...
{
"hash": "8351d991c5dfb49d534fcd28f56bb2d5b0d5f31f5c9e2e0711b5f86312a5abfe",
"witnessHash": "8351d991c5dfb49d534fcd28f56bb2d5b0d5f31f5c9e2e0711b5f86312a5abfe",
"fee": 50000,
"rate": 129198,
"mtime": 1501093478,
"height": 467,
"block": "00000000057c13f1fa6b30c6ec32284875781e31474a532e96739523d926a9e2",
"time": 1296743253,
"index": 20,
"version": 1,
"flag": 1,
"inputs": [
{
"prevout": {
"hash": "d4d30e49228051bffe1317a013c06ae53f5325302a03cdcacb3312d0998f512a",
"index": 1
},
"script": "47304402201c29f13e8d817f2c2d1ea8b89d1d603677b86d0b4658f5d836bb16c56dc5dc3e02203e815b7ef739ba95c7bbbfdd63f38baa0806ad235f73c7df2492271e0b14ea43012103d50917ce22f377797a28c5e17e33000ea7d7d149d98b942d83f25ef2a223a8aa",
"witness": "00",
"sequence": 4294967295,
"coin": {
"version": 1,
"height": 464,
"value": 457110,
"script": "76a914583d5f973c850ec26f8efa39dabf8fbe0fcbb59c88ac",
"address": "moZXHEWiTwWyy1HSwvNANn9CKoCocPzDwm",
"coinbase": false
}
},
{
"prevout": {
"hash": "3d708378adc61ad2b6d623bfbb89df92e3c88f6c85f6e132796d5abefae8c587",
"index": 1
},
"script": "0d17a6a8512d174b6b679c375091483045022100a3d133ccd4353c6dbcd9dc035c059b9b45f3c044644613e2311b8290bd02a3fb022026ae0af0adaea2fad2bc76d40d77fde3628031ee73c8e0e36343d5585e9d93f50121029f15918cd48f9e5cecfc1fccf1efc0c518110a6d6258cf14d0ee49a0fd88a535",
"witness": "00",
"sequence": 4294967295,
"coin": {
"version": 1,
"height": 466,
"value": 966270,
"script": "76a914edb1dfaf6e0b39449da811275386edf2eb54baba88ac",
"address": "n3BmXQPa1dKi3zEyCdCGNHTuE5GLdmw1Tr",
"coinbase": false
}
}
],
"outputs": [
{
"value": 1021229,
"script": "76a91419eb536dc042d76454bea8dbec5ddc384e783e5a88ac",
"address": "mht16aZhnsHivv3cDGuzgHGvoLFy8rNkg8"
},
{
"value": 352151,
"script": "76a914342e5d1f2eb9c6e99fda90c85ca05aa36616644c88ac",
"address": "mkGrySSnxcqRbtPCisApj3zXCQVmUUWbf1"
}
],
"locktime": 0
}
]
```
Returns transaction objects array by address
### HTTP Request
`GET /tx/address/:address`
### URL Parameters
Parameter | Description
--------- | -----------
:address | Bitcoin address.
## Get tx by addresses
```javascript
let address0, address1;
```
```shell--vars
address0='n3BmXQPa1dKi3zEyCdCGNHTuE5GLdmw1Tr';
address1='mwLHWwWPDwtCBZA7Ltg9QSzKK5icdCU5rb';
```
```shell--curl
curl $url/tx/address \
-H 'Content-Type: application/json' \
-X POST \
--data '{ "addresses":[ "'$address0'", "'$address1'" ]}'
```
```shell--cli
No CLI Option.
```
```javascript
const client = new bcoin.http.Client({
network: 'testnet'
});
(async () => {
await client.open();
const txs = await client.getTXByAddress([address0, address1]);
console.log(txs);
await client.close();
})().catch((err) => {
console.error(err.stack);
});
```
> The above command returns JSON structured like this:
```json
[
...
{
"hash": "4692772a73ea834c836915089acf97f2c790380a2b8fd32f82729da72545d8c5",
"witnessHash": "4692772a73ea834c836915089acf97f2c790380a2b8fd32f82729da72545d8c5",
"fee": 50000,
"rate": 134048,
"mtime": 1501093478,
"height": 500,
"block": "00000000a2424460c992803ed44cfe0c0333e91af04fde9a6a97b468bf1b5f70",
"time": 1296746771,
"index": 3,
"version": 1,
"flag": 1,
"inputs": [
{
"prevout": {
"hash": "cff00582fa957178139b0db60228fc9b252adc01ec6b11c3e16f708802c12d3f",
"index": 0
},
"script": "48304502203ef5c34af08cd2865820757844ac079e081e7b41bf427ac896f41ab12a9f9857022100bd0914548145648ec538c088640228baaa983a7c78fbf49526c5c30358fe0f54012103420f2cb862c7a77d7b2376660573eb6976f01f59222892dd16326ee7ef37fc5b",
"witness": "00",
"sequence": 4294967295,
"coin": {
"version": 1,
"height": 499,
"value": 346342,
"script": "76a914f93f789537ba00a23e7e84dcf145dae36f50ea8088ac",
"address": "n4Eras4wT4kRjX34zP96nCiHqietgeKnTn",
"coinbase": false
}
},
{
"prevout": {
"hash": "39661409f6bc4d9e08e413e01f867fe276e12e83dae89ee351df17757ca64b3f",
"index": 0
},
"script": "47304402201468bcfff3b1d8bdd0ba5fd94692c4dc7766411bdafe8d65b6e7a5be8f7efa8602207cdcbe3a107db271f24d7d8ac83a887ef4a1b72c910cc9ea5627b4cf37e87bcf0121025f9a9951e2d2a3037c1af09d9789b84a5776c504cd5b59bccd469124eb59835f",
"witness": "00",
"sequence": 4294967295,
"coin": {
"version": 1,
"height": 499,
"value": 1024528,
"script": "76a914c4a22b009b02fe8488c5543f0873e062712b7f6888ac",
"address": "mySf1HGynwyAuNyYrapRnwM83k3svzWTgD",
"coinbase": false
}
}
],
"outputs": [
{
"value": 1095497,
"script": "76a914ad7d7b9ac5260ad13fa55e06143283f5b36495f788ac",
"address": "mwLHWwWPDwtCBZA7Ltg9QSzKK5icdCU5rb"
},
{
"value": 225373,
"script": "76a914bc0f9f5fc9dc55323d52a9e354b5fb67cecd389788ac",
"address": "mxfL3bJohxaoBkKNtUF8xSU1DVKzbiChnZ"
}
],
"locktime": 0
}
]
```
Returns transaction objects array by addresses
### HTTP Request
`POST /tx/address`
### POST Parameters (JSON)
Parameter | Description
--------- | -----------
addresses | array of bitcoin addresses

1888
api-docs-slate/source/includes/_wallet.md

File diff suppressed because it is too large

231
api-docs-slate/source/includes/_wallet_accounts.md

@ -0,0 +1,231 @@
# Wallet Accounts
## Account Object
> An account object looks like this:
```json
{
"wid": 1,
"id": "test",
"name": "default",
"initialized": true,
"witness": false,
"watchOnly": false,
"type": "pubkeyhash",
"m": 1,
"n": 1,
"accountIndex": 0,
"receiveDepth": 8,
"changeDepth": 1,
"nestedDepth": 0,
"lookahead": 10,
"receiveAddress": "mu5Puppq4Es3mibRskMwoGjoZujHCFRwGS",
"nestedAddress": null,
"changeAddress": "n3nFYgQR2mrLwC3X66xHNsx4UqhS3rkSnY",
"accountKey": "tpubDC5u44zLNUVo2gPVdqCbtX644PKccH5VZB3nqUgeCiwKoi6BQZGtr5d6hhougcD6PqjszsbR3xHrQ5k8yTbUt64aSthWuNdGi7zSwfGVuxc",
"keys": []
}
```
Represents a BIP44 Account belonging to a Wallet.
Note that this object does not enforce locks. Any method that does a write is internal API only and will lead to race conditions if used elsewhere.
From the [BIP44 Specification](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki):
<p>
<code>
This level splits the key space into independent user identities, so the wallet never mixes the coins across different accounts.
</code>
</p>
<p>
<code>
Users can use these accounts to organize the funds in the same fashion as bank accounts; for donation purposes (where all addresses are considered public), for saving purposes, for common expenses etc.
</code>
</p>
<p>
<code>
Accounts are numbered from index 0 in sequentially increasing manner. This number is used as child index in BIP32 derivation.
</code>
</p>
<p>
<code>
Hardened derivation is used at this level.
</code>
</p>
## Get Wallet Account List
```shell--vars
id='test'
```
```shell--cli
bcoin cli wallet account list --id=$id
```
```javascript
const client = new bcoin.http.Client();
(async () => {
const accountInfo = await client.getAccounts(id);
console.log(accountInfo);
})();
```
> Sample response:
```json
[
"default"
]
```
List all account names (array indices map directly to bip44 account indices) associated with a specific wallet id.
### HTTP Request
`GET /wallet/:id/account`
Parameters | Description
---------- | -----------
id <br> _string_ | id of wallet you would like to retrieve the account list for
<aside class="notice">
Note that command defaults to primary (default) wallet if no wallet id is passed
</aside>
## Get Account Information
```javascript
let id, account;
```
```shell--vars
id='test'
account='default'
```
```shell--curl
curl $url/wallet/$id/account/$account
```
```shell--cli
bcoin cli wallet --id=$id account get $account
```
```javascript
const client = new bcoin.http.Client();
(async () => {
const accountInfo = await client.getAccount(id, account);
console.log(accountInfo);
})();
```
> Sample response:
```json
{
"wid": 1,
"id": "test",
"name": "default",
"initialized": true,
"witness": false,
"watchOnly": false,
"type": "pubkeyhash",
"m": 1,
"n": 1,
"accountIndex": 0,
"receiveDepth": 8,
"changeDepth": 1,
"nestedDepth": 0,
"lookahead": 10,
"receiveAddress": "mu5Puppq4Es3mibRskMwoGjoZujHCFRwGS",
"nestedAddress": null,
"changeAddress": "n3nFYgQR2mrLwC3X66xHNsx4UqhS3rkSnY",
"accountKey": "tpubDC5u44zLNUVo2gPVdqCbtX644PKccH5VZB3nqUgeCiwKoi6BQZGtr5d6hhougcD6PqjszsbR3xHrQ5k8yTbUt64aSthWuNdGi7zSwfGVuxc",
"keys": []
}
```
Get account info.
### HTTP Request
`GET /wallet/:id/account/:account`
Parameters | Description
---------- | -----------
id <br> _string_ | id of wallet you would like to query
account <br> _string_ | id of account you would to retrieve information for
## Create new wallet account
```javascript
let id, name, type;
```
```shell--vars
id='test'
name='menace'
type='multisig'
```
```shell--cli
bcoin cli wallet --id=$id account create $name --type=$type
```
```shell--curl
curl $url/wallet/$id/account/$name \
-X PUT
--data '{"type": "'$type"}'
```
```javascript
const httpWallet = new bcoin.http.Wallet({ id: id });
const options = {type: type}
(async () => {
const account = await httpWallet.createAccount(name, options);
console.log(account);
})();
```
> Sample response:
```json
{
"wid": 1,
"id": "test",
"name": "menace",
"initialized": true,
"witness": false,
"watchOnly": false,
"type": "multisig",
"m": 1,
"n": 1,
"accountIndex": 1,
"receiveDepth": 1,
"changeDepth": 1,
"nestedDepth": 0,
"lookahead": 10,
"receiveAddress": "mg7b3H3ZCHx3fwvUf8gaRHwcgsL7WdJQXv",
"nestedAddress": null,
"changeAddress": "mkYtQFpxDcqutMJtyzKNFPnn97zhft56wH",
"accountKey": "tpubDC5u44zLNUVo55dtQsJRsbQgeNfrp8ctxVEdDqDQtR7ES9XG5h1SGhkv2HCuKA2RZysaFzkuy5bgxF9egvG5BJgapWwbYMU4BJ1SeSj916G",
"keys": []
}
```
Create account with specified account name.
### HTTP Request
`PUT /wallet/:id/account/:name`
### Options object
Parameter | Description
--------- | -----------------
name <br> _string_ | name to give the account. Option can be `account` or `name`
witness <br> _bool_ | whether or not to act as segregated witness wallet account
watchOnly <br> _bool_ | whether or not to make watch only account. Watch only accounts can't accept private keys for import (or sign transactions)
type <br> _string_ | what type of wallet to make it ('multisig', 'pubkeyhash')
m <br> _int_ | for multisig accounts, what to make `m` in m-of-n
n <br> _int_ | for multisig accounts, what to make the `n` in m-of-n

162
api-docs-slate/source/includes/_wallet_admin.md

@ -0,0 +1,162 @@
# Wallet Admin
The _admin namespace exists to differentiate administrative level tasks on the wallet API that you probably don't want to expose to individual wallets.
`/wallet/_admin/[TARGET_ACTION]`
<aside class="notice">
Replace `[TARGET_ACTION]` with one of the available actions listed below
</aside>
## Wallet Rescan
```javascript
let height;
```
```shell--vars
height = 50000
```
```shell--curl
curl $url/wallet/_admin/rescan \
-X POST \
--data '{"height": '$height'}'
```
```shell--cli
bcoin cli rescan $height
```
```javascript
const height = 50000;
const client = new bcoin.http.Client({
network: 'testnet',
});
(async () => {
await client.rescan(height);
})();
```
> Response Body:
```json
{"success": true}
```
Initiates a blockchain rescan for the walletdb. Wallets will be rolled back to the specified height (transactions above this height will be unconfirmed).
### Example HTTP Request
`POST /wallet/_admin/rescan?height=50000`
## Wallet Resend
```shell--curl
curl $url/wallet/_admin/resend \
-X POST
```
```shell--cli
bcoin cli resend
```
```javascript
const client = new bcoin.http.Client({
network: 'testnet',
});
(async () => {
await client.resend();
})();
```
> Response Body:
```json
{"success": true}
```
Rebroadcast all pending transactions in all wallets.
### HTTP Request
`POST /wallet/_admin/resend`
##Wallet Backup
```javascript
let path;
```
```shell--vars
path='/path/to/new/backup'
```
```shell--curl
curl $url/wallet/_admin/backup?path=/home/user/walletdb-backup.ldb \
-X POST \
```
```shell--cli
bcoin cli backup $path
```
```javascript
const client = new bcoin.http.Client({
network: 'testnet',
});
(async () => {
await client.backup(path);
})();
```
> Response Body:
```json
{"success": true}
```
Safely backup the wallet database to specified path (creates a clone of the database).
### HTTP Request
`POST /wallet/_admin/backup?path=/home/user/walletdb-backup.ldb`
## List all Wallets
```shell--curl
curl $url/wallet/_admin/wallets
```
```shell--cli
bcoin cli wallets
```
```javascript
const client = new bcoin.http.Client({
network: 'testnet',
});
(async () => {
const wallets = await client.getWallets();
console.log(wallets)
})();
```
> Sample Response Body:
```json
[
"primary",
"test"
]
```
List all wallet IDs. Returns an array of strings.
### HTTP Request
`GET /wallet/_admin/wallets`

309
api-docs-slate/source/includes/_wallet_tx.md

@ -0,0 +1,309 @@
# Wallet Transactions
## Get Wallet TX Details
```javascript
let id, hash
```
```shell--vars
id="foo"
hash="18d2cf5683d7befe06941f59b7fb4ca0e915dcb9c6aece4ce8966a29e7c576fe"
```
```shell--cli
bcoin cli wallet --id=$id tx $hash
```
```shell--curl
curl $url/wallet/$id/tx/$hash
```
```javascript
const httpWallet = new bcoin.http.Wallet({ id: id });
(async () => {
const response = await httpWallet.getTX(hash);
console.log(response);
})();
```
> Sample Response
```json
{
"wid": 1,
"id": "foo",
"hash": "18d2cf5683d7befe06941f59b7fb4ca0e915dcb9c6aece4ce8966a29e7c576fe",
"height": -1,
"block": null,
"time": 0,
"mtime": 1507077109,
"date": "2017-10-04T00:31:49Z",
"size": 225,
"virtualSize": 225,
"fee": 4540,
"rate": 20177,
"confirmations": 0,
"inputs":
[ { value: 5000009080,
address: "SdCEuxkbdMygcKtL36x2CT8p1vhz56SsbG",
path: [Object] } ],
"outputs":
[ { value: 100000000,
address: "SP7K3cSLH66zDisioqPrTC3QSRwP9GPENB",
path: null },
{ value: 4900004540,
address: "SSzzdLbBeWBwNTUpbGdD9gBk6Wzk34sT7J",
path: [Object] } ],
"tx": "010000000148ae6682231f381845f98049c871e9b6bf0a9a7f5c5270354f71079262577977000000006a47304402203359117c409d292700fbacc03e4b540066a6b8ca763f1dd578e8262fe5e74c1b02206c91f816755469cd4a6b110941b51f29e251b86afe246456cf17823ef4fc7f5301210299c1a1049d546a720dd614034ce2802a3f64d64c37b729ae184825f71d0a037affffffff0200e1f505000000001976a91413eab6745a3fcbcf8b4448c130ff8bc37db6e91b88acbc221024010000001976a9143e9958577401fe8d75ed6f162cc6832fcb26094188ac00000000"
}
```
Get wallet transaction details.
### HTTP Request
`GET /wallet/:id/tx/:hash`
### Request Parameters
Parameter | Description
--------- | --------------
id <br> _string_ | id of wallet that handled the transaction
hash <br> _string_ | hash of the transaction you're trying to retrieve
## Delete Transaction
```javascript
let id, hash, passphrase;
```
```shell--vars
id="foo"
hash="2a22606ee555d2c26ec979f0c45cd2dc18c7177056189cb345989749fd58786"
passphrase="bar"
```
```shell--cli
# Not available in CLI
```
```shell--curl
curl $url/wallet/$id/tx/$hash \
-X DELETE \
--data '{"passphrase": "'$passphrase'"}'
```
```javascript
// Not available in javascript wallet client.
```
Abandon single pending transaction. Confirmed transactions will throw an error.
`"TX not eligible"`
### HTTP Request
`DEL /wallet/:id/tx/:hash`
Paramters | Description
----------| --------------------
id <br> _string_ | id of wallet where the transaction is that you want to remove
hash <br> _string_ | hash of transaction you would like to remove.
## Get Wallet TX History
```javascript
let id;
```
```shell--vars
id='foo'
```
```shell--cli
bcoin cli wallet --id=$id history
```
```shell--curl
curl $url/wallet/$id/tx/history
```
```javascript
const httpWallet = new bcoin.http.Wallet({ id: id });
const account = 'default';
(async () => {
const response = await httpWallet.getHistory(account);
console.log(response);
})();
```
> Sample Response
```json
[
{
"wid": 1,
"id": "primary",
"hash": "f5968051ce275d89b7a6b797eb6e6b081243ecf027872fc6949fae443e21b858",
"height": -1,
"block": null,
"time": 0,
"mtime": 1503690544,
"date": "2017-08-25T19:49:04Z",
"size": 226,
"virtualSize": 226,
"fee": 0,
"rate": 0,
"confirmations": 0,
"inputs": [
{
"value": 0,
"address": "mp2w1u4oqZnHDd1zDeAvCTX9B3SaFsUFQx",
"path": null
}
],
"outputs": [
{
"value": 100000,
"address": "myCkrhQbJwqM8wKi9YuhyTjN3pukNuWxZ9",
"path": {
"name": "default",
"account": 0,
"change": false,
"derivation": "m/0'/0/3"
}
},
{
"value": 29790920,
"address": "mqNm1rSYVqD23Aj6fkupApuSok9DNZAeBk",
"path": null
}
],
"tx": "0100000001ef8a38cc946c57634c2db05fc298bf94f5c88829c5a6e2b0610fcc7b38a9264f010000006b483045022100e98db5ddb92686fe77bb44f86ce8bf6ff693c1a1fb2fb434c6eeed7cf5e7bed4022053dca3980a902ece82fb8e9e5204c26946893388e4663dbb71e78946f49dd0f90121024c4abc2a3683891b35c04e6d40a07ee78e7d86ad9d7a14265fe214fe84513676ffffffff02a0860100000000001976a914c2013ac1a5f6a9ae91f66e71bbfae4cc762c2ca988acc892c601000000001976a9146c2483bf52052e1125fc75dd77dad06d65b70a8288ac00000000"
},
...
]
```
Get wallet TX history. Returns array of tx details.
### HTTP Request
`GET /wallet/:id/tx/history`
### Request Parameters
Paramter | Description
-------- | -------------------------
id <br> _string_ | id of wallet to get history of
## Get Pending Transactions
```javascript
let id;
```
```shell--vars
id='foo'
```
```shell--cli
bcoin cli wallet --id=$id pending
```
```shell--curl
curl $url/wallet/$id/tx/unconfirmed
```
```javascript
const httpWallet = new bcoin.http.Wallet({ id: id });
(async () => {
const response = await httpWallet.getPending(account);
console.log(response);
})();
```
Get pending wallet transactions. Returns array of tx details.
### HTTP Request
`GET /wallet/:id/tx/unconfirmed`
### Request Parameters
Paramter | Description
-------- | -------------------------
id <br> _string_ | id of wallet to get pending/unconfirmed txs
## Get Range of Transactions
```javascript
let id, account, start, end;
```
```shell--vars
id="foo"
account="foo"
start="1506909119"
end="1506909154"
```
```shell--cli
# range not available in CLI
```
```shell--curl
curl $url/wallet/$id/tx/range?start=$start
```
```javascript
const httpWallet = new bcoin.http.Wallet({ id: id });
(async () => {
const response = await httpWallet.getRange(account, {start: start, end: end});
console.log(response);
})();
```
> Sample Response
```json
[
{ "wid": 1,
"id": "primary",
"hash": "80ac63671e7b8635d10d372c4c3bed5615624d9fa28dfd747abf440417d70983",
"height": -1,
"block": null,
"time": 0,
"mtime": 1506909119,
"date": "2017-10-02T01:51:59Z",
"size": 200,
"virtualSize": 173,
"fee": 0,
"rate": 0,
"confirmations": 0,
"inputs": [ [Object] ],
"outputs": [ [Object], [Object] ],
"tx": "010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff20028d010e6d696e65642062792062636f696e045460ad97080000000000000000ffffffff02bc03062a010000001976a914d7ee508e06ece23679ba9ee0a770561ae2ed595688ac0000000000000000266a24aa21a9ed5772988727e8641cf3c7d2bf5a7fee9a5d0e827de0b6bed5658eee8f0821b5200120000000000000000000000000000000000000000000000000000000000000000000000000"
},
...
]
```
Get range of wallet transactions by timestamp. Returns array of tx details.
<aside class="notice">
Note that there are other options documented that `getRange` accepts in the options body, `limit` and `reverse`. At the time of writing however they do not have any effect.
</aside>
### HTTP Request
`GET /wallet/:id/tx/range`
### Body Parameters
Paramter | Description
-------- | -------------------------
account <br>_string_ | account to get the tx history from
start <br> _int_ | start time to get range from
end <br> _int_ | end time to get range from
<!-- ##GET /wallet/:id/tx/last
Get last N wallet transactions.
### HTTP Request
`GET /wallet/:id/tx/last` -->

80
api-docs-slate/source/index.html.md

@ -0,0 +1,80 @@
---
title: Bcoin API Reference
home_link: http://bcoin.io
language_tabs: # must be one of https://git.io/vQNgJ
- shell--curl: cURL
- shell--cli: CLI
- javascript
toc_footers:
- <a href='http://bcoin.io/slack-signup.html'>Join us on Slack</a>
- <a href='https://github.com/bcoin-org/bcoin'>See the code on GitHub</a>
- <a href='http://bcoin.io/guides.html'>Browse the guides</a>
- <a href='http://bcoin.io/docs/index.html'>Full API Documentation</a>
- <a href='https://github.com/tripit/slate'>Documentation Powered by Slate</a>
includes:
- clients
- node
- node_rpc
- node_rpc_general
- node_rpc_chain
- node_rpc_block
- node_rpc_mempool
- node_rpc_tx
- node_rpc_mining
- node_rpc_network
- coin
- transaction
- wallet_admin
- wallet
- wallet_tx
- wallet_accounts
- errors
search: true
---
# Introduction
Welcome to the Bcoin API!
The default bcoin HTTP server listens on the standard RPC port (`8332` for main, `18332` for testnet, `48332` for regtest, and `18556` default for simnet). It exposes a REST json api, as well as a JSON-RPC api.
# Authentication
## Auth
```shell--curl
curl http://x:[api-key]@127.0.0.1:8332/
```
```shell--cli
export BCOIN_API_KEY=[api-key]
bcoin cli info
```
```javascript
const client = new bcoin.http.Client({
apiKey: [api-key],
//...
});
// Or wallet
const wallet = new bcoin.http.Wallet({
apiKey: [api-key],
//...
});
```
> Make sure to replace `[api-key]` with your own key.
Auth is accomplished via HTTP Basic Auth, using your node's API key (passed via --api-key).
<aside class="notice">
You must replace <code>[api-key]</code> with your personal API key.
</aside>
<aside class="warning">
If you intend to use API via network and setup <code>api-key</code>, make sure to setup <code>ssl</code> too.
</aside>

2
api-docs-slate/source/javascripts/all.js

@ -0,0 +1,2 @@
//= require ./all_nosearch
//= require ./app/_search

16
api-docs-slate/source/javascripts/all_nosearch.js

@ -0,0 +1,16 @@
//= require ./lib/_energize
//= require ./app/_toc
//= require ./app/_lang
$(function() {
loadToc($('#toc'), '.toc-link', '.toc-list-h2', 10);
setupLanguages($('body').data('languages'));
$('.content').imagesLoaded( function() {
window.recacheHeights();
window.refreshToc();
});
});
window.onpopstate = function() {
activateLanguage(getLanguageFromQueryString());
};

164
api-docs-slate/source/javascripts/app/_lang.js

@ -0,0 +1,164 @@
//= require ../lib/_jquery
/*
Copyright 2008-2013 Concur Technologies, Inc.
Licensed under the Apache License, Version 2.0 (the "License"); you may
not use this file except in compliance with the License. You may obtain
a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations
under the License.
*/
;(function () {
'use strict';
var languages = [];
window.setupLanguages = setupLanguages;
window.activateLanguage = activateLanguage;
window.getLanguageFromQueryString = getLanguageFromQueryString;
function activateLanguage(language) {
if (!language) return;
if (language === "") return;
$(".lang-selector a").removeClass('active');
$(".lang-selector a[data-language-name='" + language + "']").addClass('active');
for (var i=0; i < languages.length; i++) {
$(".highlight.tab-" + languages[i]).hide();
$(".lang-specific." + languages[i]).hide();
}
$(".highlight.tab-" + language).show();
$(".lang-specific." + language).show();
window.recacheHeights();
// scroll to the new location of the position
if ($(window.location.hash).get(0)) {
$(window.location.hash).get(0).scrollIntoView(true);
}
}
// parseURL and stringifyURL are from https://github.com/sindresorhus/query-string
// MIT licensed
// https://github.com/sindresorhus/query-string/blob/7bee64c16f2da1a326579e96977b9227bf6da9e6/license
function parseURL(str) {
if (typeof str !== 'string') {
return {};
}
str = str.trim().replace(/^(\?|#|&)/, '');
if (!str) {
return {};
}
return str.split('&').reduce(function (ret, param) {
var parts = param.replace(/\+/g, ' ').split('=');
var key = parts[0];
var val = parts[1];
key = decodeURIComponent(key);
// missing `=` should be `null`:
// http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters
val = val === undefined ? null : decodeURIComponent(val);
if (!ret.hasOwnProperty(key)) {
ret[key] = val;
} else if (Array.isArray(ret[key])) {
ret[key].push(val);
} else {
ret[key] = [ret[key], val];
}
return ret;
}, {});
};
function stringifyURL(obj) {
return obj ? Object.keys(obj).sort().map(function (key) {
var val = obj[key];
if (Array.isArray(val)) {
return val.sort().map(function (val2) {
return encodeURIComponent(key) + '=' + encodeURIComponent(val2);
}).join('&');
}
return encodeURIComponent(key) + '=' + encodeURIComponent(val);
}).join('&') : '';
};
// gets the language set in the query string
function getLanguageFromQueryString() {
if (location.search.length >= 1) {
var language = parseURL(location.search).language
if (language) {
return language;
} else if (jQuery.inArray(location.search.substr(1), languages) != -1) {
return location.search.substr(1);
}
}
return false;
}
// returns a new query string with the new language in it
function generateNewQueryString(language) {
var url = parseURL(location.search);
if (url.language) {
url.language = language;
return stringifyURL(url);
}
return language;
}
// if a button is clicked, add the state to the history
function pushURL(language) {
if (!history) { return; }
var hash = window.location.hash;
if (hash) {
hash = hash.replace(/^#+/, '');
}
history.pushState({}, '', '?' + generateNewQueryString(language) + '#' + hash);
// save language as next default
localStorage.setItem("language", language);
}
function setupLanguages(l) {
var defaultLanguage = localStorage.getItem("language");
languages = l;
var presetLanguage = getLanguageFromQueryString();
if (presetLanguage) {
// the language is in the URL, so use that language!
activateLanguage(presetLanguage);
localStorage.setItem("language", presetLanguage);
} else if ((defaultLanguage !== null) && (jQuery.inArray(defaultLanguage, languages) != -1)) {
// the language was the last selected one saved in localstorage, so use that language!
activateLanguage(defaultLanguage);
} else {
// no language selected, so use the default
activateLanguage(languages[0]);
}
}
// if we click on a language tab, activate that language
$(function() {
$(".lang-selector a").on("click", function() {
var language = $(this).data("language-name");
pushURL(language);
activateLanguage(language);
return false;
});
});
})();

98
api-docs-slate/source/javascripts/app/_search.js

@ -0,0 +1,98 @@
//= require ../lib/_lunr
//= require ../lib/_jquery
//= require ../lib/_jquery.highlight
;(function () {
'use strict';
var content, searchResults;
var highlightOpts = { element: 'span', className: 'search-highlight' };
var searchDelay = 0;
var timeoutHandle = 0;
var index = new lunr.Index();
index.ref('id');
index.field('title', { boost: 10 });
index.field('body');
index.pipeline.add(lunr.trimmer, lunr.stopWordFilter);
$(populate);
$(bind);
function populate() {
$('h1, h2').each(function() {
var title = $(this);
var body = title.nextUntil('h1, h2');
index.add({
id: title.prop('id'),
title: title.text(),
body: body.text()
});
});
determineSearchDelay();
}
function determineSearchDelay() {
if(index.tokenStore.length>5000) {
searchDelay = 300;
}
}
function bind() {
content = $('.content');
searchResults = $('.search-results');
$('#input-search').on('keyup',function(e) {
var wait = function() {
return function(executingFunction, waitTime){
clearTimeout(timeoutHandle);
timeoutHandle = setTimeout(executingFunction, waitTime);
};
}();
wait(function(){
search(e);
}, searchDelay );
});
}
function search(event) {
var searchInput = $('#input-search')[0];
unhighlight();
searchResults.addClass('visible');
// ESC clears the field
if (event.keyCode === 27) searchInput.value = '';
if (searchInput.value) {
var results = index.search(searchInput.value).filter(function(r) {
return r.score > 0.0001;
});
if (results.length) {
searchResults.empty();
$.each(results, function (index, result) {
var elem = document.getElementById(result.ref);
searchResults.append("<li><a href='#" + result.ref + "'>" + $(elem).text() + "</a></li>");
});
highlight.call(searchInput);
} else {
searchResults.html('<li></li>');
$('.search-results li').text('No Results Found for "' + searchInput.value + '"');
}
} else {
unhighlight();
searchResults.removeClass('visible');
}
}
function highlight() {
if (this.value) content.highlight(this.value, highlightOpts);
}
function unhighlight() {
content.unhighlight(highlightOpts);
}
})();

117
api-docs-slate/source/javascripts/app/_toc.js

@ -0,0 +1,117 @@
//= require ../lib/_jquery
//= require ../lib/_imagesloaded.min
;(function () {
'use strict';
var loaded = false;
var debounce = function(func, waitTime) {
var timeout = false;
return function() {
if (timeout === false) {
setTimeout(function() {
func();
timeout = false;
}, waitTime);
timeout = true;
}
};
};
var closeToc = function() {
$(".toc-wrapper").removeClass('open');
$("#nav-button").removeClass('open');
};
function loadToc($toc, tocLinkSelector, tocListSelector, scrollOffset) {
var headerHeights = {};
var pageHeight = 0;
var windowHeight = 0;
var originalTitle = document.title;
var recacheHeights = function() {
headerHeights = {};
pageHeight = $(document).height();
windowHeight = $(window).height();
$toc.find(tocLinkSelector).each(function() {
var targetId = $(this).attr('href');
if (targetId[0] === "#") {
headerHeights[targetId] = $(targetId).offset().top;
}
});
};
var refreshToc = function() {
var currentTop = $(document).scrollTop() + scrollOffset;
if (currentTop + windowHeight >= pageHeight) {
// at bottom of page, so just select last header by making currentTop very large
// this fixes the problem where the last header won't ever show as active if its content
// is shorter than the window height
currentTop = pageHeight + 1000;
}
var best = null;
for (var name in headerHeights) {
if ((headerHeights[name] < currentTop && headerHeights[name] > headerHeights[best]) || best === null) {
best = name;
}
}
// Catch the initial load case
if (currentTop == scrollOffset && !loaded) {
best = window.location.hash;
loaded = true;
}
var $best = $toc.find("[href='" + best + "']").first();
if (!$best.hasClass("active")) {
// .active is applied to the ToC link we're currently on, and its parent <ul>s selected by tocListSelector
// .active-expanded is applied to the ToC links that are parents of this one
$toc.find(".active").removeClass("active");
$toc.find(".active-parent").removeClass("active-parent");
$best.addClass("active");
$best.parents(tocListSelector).addClass("active").siblings(tocLinkSelector).addClass('active-parent');
$best.siblings(tocListSelector).addClass("active");
$toc.find(tocListSelector).filter(":not(.active)").slideUp(150);
$toc.find(tocListSelector).filter(".active").slideDown(150);
if (window.history.pushState) {
window.history.pushState(null, "", best);
}
// TODO remove classnames
document.title = $best.data("title") + " – " + originalTitle;
}
};
var makeToc = function() {
recacheHeights();
refreshToc();
$("#nav-button").click(function() {
$(".toc-wrapper").toggleClass('open');
$("#nav-button").toggleClass('open');
return false;
});
$(".page-wrapper").click(closeToc);
$(".toc-link").click(closeToc);
// reload immediately after scrolling on toc click
$toc.find(tocLinkSelector).click(function() {
setTimeout(function() {
refreshToc();
}, 0);
});
$(window).scroll(debounce(refreshToc, 200));
$(window).resize(debounce(recacheHeights, 200));
};
makeToc();
window.recacheHeights = recacheHeights;
window.refreshToc = refreshToc;
}
window.loadToc = loadToc;
})();

169
api-docs-slate/source/javascripts/lib/_energize.js

@ -0,0 +1,169 @@
/**
* energize.js v0.1.0
*
* Speeds up click events on mobile devices.
* https://github.com/davidcalhoun/energize.js
*/
(function() { // Sandbox
/**
* Don't add to non-touch devices, which don't need to be sped up
*/
if(!('ontouchstart' in window)) return;
var lastClick = {},
isThresholdReached, touchstart, touchmove, touchend,
click, closest;
/**
* isThresholdReached
*
* Compare touchstart with touchend xy coordinates,
* and only fire simulated click event if the coordinates
* are nearby. (don't want clicking to be confused with a swipe)
*/
isThresholdReached = function(startXY, xy) {
return Math.abs(startXY[0] - xy[0]) > 5 || Math.abs(startXY[1] - xy[1]) > 5;
};
/**
* touchstart
*
* Save xy coordinates when the user starts touching the screen
*/
touchstart = function(e) {
this.startXY = [e.touches[0].clientX, e.touches[0].clientY];
this.threshold = false;
};
/**
* touchmove
*
* Check if the user is scrolling past the threshold.
* Have to check here because touchend will not always fire
* on some tested devices (Kindle Fire?)
*/
touchmove = function(e) {
// NOOP if the threshold has already been reached
if(this.threshold) return false;
this.threshold = isThresholdReached(this.startXY, [e.touches[0].clientX, e.touches[0].clientY]);
};
/**
* touchend
*
* If the user didn't scroll past the threshold between
* touchstart and touchend, fire a simulated click.
*
* (This will fire before a native click)
*/
touchend = function(e) {
// Don't fire a click if the user scrolled past the threshold
if(this.threshold || isThresholdReached(this.startXY, [e.changedTouches[0].clientX, e.changedTouches[0].clientY])) {
return;
}
/**
* Create and fire a click event on the target element
* https://developer.mozilla.org/en/DOM/event.initMouseEvent
*/
var touch = e.changedTouches[0],
evt = document.createEvent('MouseEvents');
evt.initMouseEvent('click', true, true, window, 0, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
evt.simulated = true; // distinguish from a normal (nonsimulated) click
e.target.dispatchEvent(evt);
};
/**
* click
*
* Because we've already fired a click event in touchend,
* we need to listed for all native click events here
* and suppress them as necessary.
*/
click = function(e) {
/**
* Prevent ghost clicks by only allowing clicks we created
* in the click event we fired (look for e.simulated)
*/
var time = Date.now(),
timeDiff = time - lastClick.time,
x = e.clientX,
y = e.clientY,
xyDiff = [Math.abs(lastClick.x - x), Math.abs(lastClick.y - y)],
target = closest(e.target, 'A') || e.target, // needed for standalone apps
nodeName = target.nodeName,
isLink = nodeName === 'A',
standAlone = window.navigator.standalone && isLink && e.target.getAttribute("href");
lastClick.time = time;
lastClick.x = x;
lastClick.y = y;
/**
* Unfortunately Android sometimes fires click events without touch events (seen on Kindle Fire),
* so we have to add more logic to determine the time of the last click. Not perfect...
*
* Older, simpler check: if((!e.simulated) || standAlone)
*/
if((!e.simulated && (timeDiff < 500 || (timeDiff < 1500 && xyDiff[0] < 50 && xyDiff[1] < 50))) || standAlone) {
e.preventDefault();
e.stopPropagation();
if(!standAlone) return false;
}
/**
* Special logic for standalone web apps
* See http://stackoverflow.com/questions/2898740/iphone-safari-web-app-opens-links-in-new-window
*/
if(standAlone) {
window.location = target.getAttribute("href");
}
/**
* Add an energize-focus class to the targeted link (mimics :focus behavior)
* TODO: test and/or remove? Does this work?
*/
if(!target || !target.classList) return;
target.classList.add("energize-focus");
window.setTimeout(function(){
target.classList.remove("energize-focus");
}, 150);
};
/**
* closest
* @param {HTMLElement} node current node to start searching from.
* @param {string} tagName the (uppercase) name of the tag you're looking for.
*
* Find the closest ancestor tag of a given node.
*
* Starts at node and goes up the DOM tree looking for a
* matching nodeName, continuing until hitting document.body
*/
closest = function(node, tagName){
var curNode = node;
while(curNode !== document.body) { // go up the dom until we find the tag we're after
if(!curNode || curNode.nodeName === tagName) { return curNode; } // found
curNode = curNode.parentNode; // not found, so keep going up
}
return null; // not found
};
/**
* Add all delegated event listeners
*
* All the events we care about bubble up to document,
* so we can take advantage of event delegation.
*
* Note: no need to wait for DOMContentLoaded here
*/
document.addEventListener('touchstart', touchstart, false);
document.addEventListener('touchmove', touchmove, false);
document.addEventListener('touchend', touchend, false);
document.addEventListener('click', click, true); // TODO: why does this use capture?
})();

7
api-docs-slate/source/javascripts/lib/_imagesloaded.min.js

File diff suppressed because one or more lines are too long

108
api-docs-slate/source/javascripts/lib/_jquery.highlight.js

@ -0,0 +1,108 @@
/*
* jQuery Highlight plugin
*
* Based on highlight v3 by Johann Burkard
* http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html
*
* Code a little bit refactored and cleaned (in my humble opinion).
* Most important changes:
* - has an option to highlight only entire words (wordsOnly - false by default),
* - has an option to be case sensitive (caseSensitive - false by default)
* - highlight element tag and class names can be specified in options
*
* Usage:
* // wrap every occurrance of text 'lorem' in content
* // with <span class='highlight'> (default options)
* $('#content').highlight('lorem');
*
* // search for and highlight more terms at once
* // so you can save some time on traversing DOM
* $('#content').highlight(['lorem', 'ipsum']);
* $('#content').highlight('lorem ipsum');
*
* // search only for entire word 'lorem'
* $('#content').highlight('lorem', { wordsOnly: true });
*
* // don't ignore case during search of term 'lorem'
* $('#content').highlight('lorem', { caseSensitive: true });
*
* // wrap every occurrance of term 'ipsum' in content
* // with <em class='important'>
* $('#content').highlight('ipsum', { element: 'em', className: 'important' });
*
* // remove default highlight
* $('#content').unhighlight();
*
* // remove custom highlight
* $('#content').unhighlight({ element: 'em', className: 'important' });
*
*
* Copyright (c) 2009 Bartek Szopka
*
* Licensed under MIT license.
*
*/
jQuery.extend({
highlight: function (node, re, nodeName, className) {
if (node.nodeType === 3) {
var match = node.data.match(re);
if (match) {
var highlight = document.createElement(nodeName || 'span');
highlight.className = className || 'highlight';
var wordNode = node.splitText(match.index);
wordNode.splitText(match[0].length);
var wordClone = wordNode.cloneNode(true);
highlight.appendChild(wordClone);
wordNode.parentNode.replaceChild(highlight, wordNode);
return 1; //skip added node in parent
}
} else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children
!/(script|style)/i.test(node.tagName) && // ignore script and style nodes
!(node.tagName === nodeName.toUpperCase() && node.className === className)) { // skip if already highlighted
for (var i = 0; i < node.childNodes.length; i++) {
i += jQuery.highlight(node.childNodes[i], re, nodeName, className);
}
}
return 0;
}
});
jQuery.fn.unhighlight = function (options) {
var settings = { className: 'highlight', element: 'span' };
jQuery.extend(settings, options);
return this.find(settings.element + "." + settings.className).each(function () {
var parent = this.parentNode;
parent.replaceChild(this.firstChild, this);
parent.normalize();
}).end();
};
jQuery.fn.highlight = function (words, options) {
var settings = { className: 'highlight', element: 'span', caseSensitive: false, wordsOnly: false };
jQuery.extend(settings, options);
if (words.constructor === String) {
words = [words];
}
words = jQuery.grep(words, function(word, i){
return word != '';
});
words = jQuery.map(words, function(word, i) {
return word.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
});
if (words.length == 0) { return this; };
var flag = settings.caseSensitive ? "" : "i";
var pattern = "(" + words.join("|") + ")";
if (settings.wordsOnly) {
pattern = "\\b" + pattern + "\\b";
}
var re = new RegExp(pattern, flag);
return this.each(function () {
jQuery.highlight(this, re, settings.element, settings.className);
});
};

9831
api-docs-slate/source/javascripts/lib/_jquery.js

File diff suppressed because it is too large

1910
api-docs-slate/source/javascripts/lib/_lunr.js

File diff suppressed because it is too large

122
api-docs-slate/source/layouts/layout.erb

@ -0,0 +1,122 @@
<%#
Copyright 2008-2013 Concur Technologies, Inc.
Licensed under the Apache License, Version 2.0 (the "License"); you may
not use this file except in compliance with the License. You may obtain
a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations
under the License.
%>
<% language_tabs = current_page.data.language_tabs || [] %>
<% page_content = yield %>
<%
if current_page.data.includes
current_page.data.includes.each do |include|
page_content += partial("includes/#{include}")
end
end
%>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title><%= current_page.data.title || "API Documentation" %></title>
<style>
<%= Rouge::Themes::MonokaiSublime.render(:scope => '.highlight') %>
</style>
<%= stylesheet_link_tag :screen, media: :screen %>
<%= stylesheet_link_tag :print, media: :print %>
<% if current_page.data.search %>
<%= javascript_include_tag "all" %>
<% else %>
<%= javascript_include_tag "all_nosearch" %>
<% end %>
</head>
<body class="<%= page_classes %>" data-languages="<%=h language_tabs.map{ |lang| lang.is_a?(Hash) ? lang.keys.first : lang }.to_json %>">
<a href="#" id="nav-button">
<span>
NAV
<%= image_tag('navbar.png') %>
</span>
</a>
<div class="toc-wrapper">
<% if current_page.data.home_link %>
<a href="<%= current_page.data.home_link %>">
<% end %>
<%= image_tag "logo.png", class: 'logo' %>
<% if current_page.data.home_link %>
</a>
<% end %>
<% if language_tabs.any? %>
<div class="lang-selector">
<% language_tabs.each do |lang| %>
<% if lang.is_a? Hash %>
<a href="#" data-language-name="<%= lang.keys.first %>"><%= lang.values.first %></a>
<% else %>
<a href="#" data-language-name="<%= lang %>"><%= lang %></a>
<% end %>
<% end %>
</div>
<% end %>
<% if current_page.data.search %>
<div class="search">
<input type="text" class="search" id="input-search" placeholder="Search">
</div>
<ul class="search-results"></ul>
<% end %>
<div id="toc" class="toc-list-h1">
<% toc_data(page_content).each do |h1| %>
<li>
<a href="#<%= h1[:id] %>" class="toc-h1 toc-link" data-title="<%= h1[:content] %>"><%= h1[:content] %></a>
<% if h1[:children].length > 0 %>
<ul class="toc-list-h2">
<% h1[:children].each do |h2| %>
<li>
<a href="#<%= h2[:id] %>" class="toc-h2 toc-link" data-title="<%= h1[:content] %>"><%= h2[:content] %></a>
</li>
<% end %>
</ul>
<% end %>
</li>
<% end %>
</div>
<% if current_page.data.toc_footers %>
<ul class="toc-footer">
<% current_page.data.toc_footers.each do |footer| %>
<li><%= footer %></li>
<% end %>
</ul>
<% end %>
</div>
<div class="page-wrapper">
<div class="dark-box"></div>
<div class="content">
<%= page_content %>
</div>
<div class="dark-box">
<% if language_tabs.any? %>
<div class="lang-selector">
<% language_tabs.each do |lang| %>
<% if lang.is_a? Hash %>
<a href="#" data-language-name="<%= lang.keys.first %>"><%= lang.values.first %></a>
<% else %>
<a href="#" data-language-name="<%= lang %>"><%= lang %></a>
<% end %>
<% end %>
</div>
<% end %>
</div>
</div>
</body>
</html>

48
api-docs-slate/source/stylesheets/_custom.scss

@ -0,0 +1,48 @@
.page-wrapper {
background-color: #dadee0;
}
.toc-wrapper .logo {
width: 60%;
margin: 20px 0 20px 15px;
}
.highlight .s1 {
color: #c991f9;
}
.highlight .s2 {
color: #b0faff;
}
.highlight .nb {
color: #ffa900;
}
.highlight .o {
color: #ff005c;
}
.highlight .kc {
color: #29adff;
}
.highlight .na {
color: #ccec8a;
}
.page-wrapper .dark-box {
background-color: #474f52;
}
.content aside {
background: #b3c4fb;
}
.content aside.warning {
background-color: #c0b3f3;
}
.toc-wrapper .toc-link.active {
background-color: #5659dc;
}

38
api-docs-slate/source/stylesheets/_icon-font.scss

@ -0,0 +1,38 @@
@font-face {
font-family: 'slate';
src:font-url('slate.eot?-syv14m');
src:font-url('slate.eot?#iefix-syv14m') format('embedded-opentype'),
font-url('slate.woff2?-syv14m') format('woff2'),
font-url('slate.woff?-syv14m') format('woff'),
font-url('slate.ttf?-syv14m') format('truetype'),
font-url('slate.svg?-syv14m#slate') format('svg');
font-weight: normal;
font-style: normal;
}
%icon {
font-family: 'slate';
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
}
%icon-exclamation-sign {
@extend %icon;
content: "\e600";
}
%icon-info-sign {
@extend %icon;
content: "\e602";
}
%icon-ok-sign {
@extend %icon;
content: "\e606";
}
%icon-search {
@extend %icon;
content: "\e607";
}

427
api-docs-slate/source/stylesheets/_normalize.scss

@ -0,0 +1,427 @@
/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
/**
* 1. Set default font family to sans-serif.
* 2. Prevent iOS text size adjust after orientation change, without disabling
* user zoom.
*/
html {
font-family: sans-serif; /* 1 */
-ms-text-size-adjust: 100%; /* 2 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/**
* Remove default margin.
*/
body {
margin: 0;
}
/* HTML5 display definitions
========================================================================== */
/**
* Correct `block` display not defined for any HTML5 element in IE 8/9.
* Correct `block` display not defined for `details` or `summary` in IE 10/11
* and Firefox.
* Correct `block` display not defined for `main` in IE 11.
*/
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
main,
menu,
nav,
section,
summary {
display: block;
}
/**
* 1. Correct `inline-block` display not defined in IE 8/9.
* 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
*/
audio,
canvas,
progress,
video {
display: inline-block; /* 1 */
vertical-align: baseline; /* 2 */
}
/**
* Prevent modern browsers from displaying `audio` without controls.
* Remove excess height in iOS 5 devices.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/**
* Address `[hidden]` styling not present in IE 8/9/10.
* Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
*/
[hidden],
template {
display: none;
}
/* Links
========================================================================== */
/**
* Remove the gray background color from active links in IE 10.
*/
a {
background-color: transparent;
}
/**
* Improve readability when focused and also mouse hovered in all browsers.
*/
a:active,
a:hover {
outline: 0;
}
/* Text-level semantics
========================================================================== */
/**
* Address styling not present in IE 8/9/10/11, Safari, and Chrome.
*/
abbr[title] {
border-bottom: 1px dotted;
}
/**
* Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
*/
b,
strong {
font-weight: bold;
}
/**
* Address styling not present in Safari and Chrome.
*/
dfn {
font-style: italic;
}
/**
* Address variable `h1` font-size and margin within `section` and `article`
* contexts in Firefox 4+, Safari, and Chrome.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/**
* Address styling not present in IE 8/9.
*/
mark {
background: #ff0;
color: #000;
}
/**
* Address inconsistent and variable font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` affecting `line-height` in all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sup {
top: -0.5em;
}
sub {
bottom: -0.25em;
}
/* Embedded content
========================================================================== */
/**
* Remove border when inside `a` element in IE 8/9/10.
*/
img {
border: 0;
}
/**
* Correct overflow not hidden in IE 9/10/11.
*/
svg:not(:root) {
overflow: hidden;
}
/* Grouping content
========================================================================== */
/**
* Address margin not present in IE 8/9 and Safari.
*/
figure {
margin: 1em 40px;
}
/**
* Address differences between Firefox and other browsers.
*/
hr {
-moz-box-sizing: content-box;
box-sizing: content-box;
height: 0;
}
/**
* Contain overflow in all browsers.
*/
pre {
overflow: auto;
}
/**
* Address odd `em`-unit font size rendering in all browsers.
*/
code,
kbd,
pre,
samp {
font-family: monospace, monospace;
font-size: 1em;
}
/* Forms
========================================================================== */
/**
* Known limitation: by default, Chrome and Safari on OS X allow very limited
* styling of `select`, unless a `border` property is set.
*/
/**
* 1. Correct color not being inherited.
* Known issue: affects color of disabled elements.
* 2. Correct font properties not being inherited.
* 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
*/
button,
input,
optgroup,
select,
textarea {
color: inherit; /* 1 */
font: inherit; /* 2 */
margin: 0; /* 3 */
}
/**
* Address `overflow` set to `hidden` in IE 8/9/10/11.
*/
button {
overflow: visible;
}
/**
* Address inconsistent `text-transform` inheritance for `button` and `select`.
* All other form control elements do not inherit `text-transform` values.
* Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
* Correct `select` style inheritance in Firefox.
*/
button,
select {
text-transform: none;
}
/**
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
* and `video` controls.
* 2. Correct inability to style clickable `input` types in iOS.
* 3. Improve usability and consistency of cursor style between image-type
* `input` and others.
*/
button,
html input[type="button"], /* 1 */
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button; /* 2 */
cursor: pointer; /* 3 */
}
/**
* Re-set default cursor for disabled elements.
*/
button[disabled],
html input[disabled] {
cursor: default;
}
/**
* Remove inner padding and border in Firefox 4+.
*/
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}
/**
* Address Firefox 4+ setting `line-height` on `input` using `!important` in
* the UA stylesheet.
*/
input {
line-height: normal;
}
/**
* It's recommended that you don't attempt to style these elements.
* Firefox's implementation doesn't respect box-sizing, padding, or width.
*
* 1. Address box sizing set to `content-box` in IE 8/9/10.
* 2. Remove excess padding in IE 8/9/10.
*/
input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Fix the cursor style for Chrome's increment/decrement buttons. For certain
* `font-size` values of the `input`, it causes the cursor style of the
* decrement button to change from `default` to `text`.
*/
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Address `appearance` set to `searchfield` in Safari and Chrome.
* 2. Address `box-sizing` set to `border-box` in Safari and Chrome
* (include `-moz` to future-proof).
*/
input[type="search"] {
-webkit-appearance: textfield; /* 1 */
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box; /* 2 */
box-sizing: content-box;
}
/**
* Remove inner padding and search cancel button in Safari and Chrome on OS X.
* Safari (but not Chrome) clips the cancel button when the search input has
* padding (and `textfield` appearance).
*/
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* Define consistent border, margin, and padding.
*/
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
/**
* 1. Correct `color` not being inherited in IE 8/9/10/11.
* 2. Remove padding so people aren't caught out if they zero out fieldsets.
*/
legend {
border: 0; /* 1 */
padding: 0; /* 2 */
}
/**
* Remove default vertical scrollbar in IE 8/9/10/11.
*/
textarea {
overflow: auto;
}
/**
* Don't inherit the `font-weight` (applied by a rule above).
* NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
*/
optgroup {
font-weight: bold;
}
/* Tables
========================================================================== */
/**
* Remove most spacing between table cells.
*/
table {
border-collapse: collapse;
border-spacing: 0;
}
td,
th {
padding: 0;
}

103
api-docs-slate/source/stylesheets/_variables.scss

@ -0,0 +1,103 @@
/*
Copyright 2008-2013 Concur Technologies, Inc.
Licensed under the Apache License, Version 2.0 (the "License"); you may
not use this file except in compliance with the License. You may obtain
a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations
under the License.
*/
////////////////////////////////////////////////////////////////////////////////
// CUSTOMIZE SLATE
////////////////////////////////////////////////////////////////////////////////
// Use these settings to help adjust the appearance of Slate
// BACKGROUND COLORS
////////////////////
$nav-bg: #2E3336 !default;
$examples-bg: #2E3336 !default;
$code-bg: #1E2224 !default;
$code-annotation-bg: #191D1F !default;
$nav-subitem-bg: #1E2224 !default;
$nav-active-bg: #0F75D4 !default;
$nav-active-parent-bg: #1E2224 !default; // parent links of the current section
$lang-select-border: #000 !default;
$lang-select-bg: #1E2224 !default;
$lang-select-active-bg: $examples-bg !default; // feel free to change this to blue or something
$lang-select-pressed-bg: #111 !default; // color of language tab bg when mouse is pressed
$main-bg: #F3F7F9 !default;
$aside-notice-bg: #8fbcd4 !default;
$aside-warning-bg: #c97a7e !default;
$aside-success-bg: #6ac174 !default;
$search-notice-bg: #c97a7e !default;
// TEXT COLORS
////////////////////
$main-text: #333 !default; // main content text color
$nav-text: #fff !default;
$nav-active-text: #fff !default;
$nav-active-parent-text: #fff !default; // parent links of the current section
$lang-select-text: #fff !default; // color of unselected language tab text
$lang-select-active-text: #fff !default; // color of selected language tab text
$lang-select-pressed-text: #fff !default; // color of language tab text when mouse is pressed
// SIZES
////////////////////
$nav-width: 230px !default; // width of the navbar
$examples-width: 50% !default; // portion of the screen taken up by code examples
$logo-margin: 0px !default; // margin below logo
$main-padding: 28px !default; // padding to left and right of content & examples
$nav-padding: 15px !default; // padding to left and right of navbar
$nav-v-padding: 10px !default; // padding used vertically around search boxes and results
$nav-indent: 10px !default; // extra padding for ToC subitems
$code-annotation-padding: 13px !default; // padding inside code annotations
$h1-margin-bottom: 21px !default; // padding under the largest header tags
$tablet-width: 930px !default; // min width before reverting to tablet size
$phone-width: $tablet-width - $nav-width !default; // min width before reverting to mobile size
// FONTS
////////////////////
%default-font {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
font-size: 14px;
}
%header-font {
@extend %default-font;
font-weight: bold;
}
%code-font {
font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, serif;
font-size: 12px;
line-height: 1.5;
}
// OTHER
////////////////////
$nav-footer-border-color: #666 !default;
$search-box-border-color: #666 !default;
////////////////////////////////////////////////////////////////////////////////
// INTERNAL
////////////////////////////////////////////////////////////////////////////////
// These settings are probably best left alone.
%break-words {
word-break: break-all;
hyphens: auto;
}

147
api-docs-slate/source/stylesheets/print.css.scss

@ -0,0 +1,147 @@
@charset "utf-8";
@import 'normalize';
@import 'variables';
@import 'icon-font';
/*
Copyright 2008-2013 Concur Technologies, Inc.
Licensed under the Apache License, Version 2.0 (the "License"); you may
not use this file except in compliance with the License. You may obtain
a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations
under the License.
*/
$print-color: #999;
$print-color-light: #ccc;
$print-font-size: 12px;
body {
@extend %default-font;
}
.tocify, .toc-footer, .lang-selector, .search, #nav-button {
display: none;
}
.tocify-wrapper>img {
margin: 0 auto;
display: block;
}
.content {
font-size: 12px;
pre, code {
@extend %code-font;
@extend %break-words;
border: 1px solid $print-color;
border-radius: 5px;
font-size: 0.8em;
}
pre {
code {
border: 0;
}
}
pre {
padding: 1.3em;
}
code {
padding: 0.2em;
}
table {
border: 1px solid $print-color;
tr {
border-bottom: 1px solid $print-color;
}
td,th {
padding: 0.7em;
}
}
p {
line-height: 1.5;
}
a {
text-decoration: none;
color: #000;
}
h1 {
@extend %header-font;
font-size: 2.5em;
padding-top: 0.5em;
padding-bottom: 0.5em;
margin-top: 1em;
margin-bottom: $h1-margin-bottom;
border: 2px solid $print-color-light;
border-width: 2px 0;
text-align: center;
}
h2 {
@extend %header-font;
font-size: 1.8em;
margin-top: 2em;
border-top: 2px solid $print-color-light;
padding-top: 0.8em;
}
h1+h2, h1+div+h2 {
border-top: none;
padding-top: 0;
margin-top: 0;
}
h3, h4 {
@extend %header-font;
font-size: 0.8em;
margin-top: 1.5em;
margin-bottom: 0.8em;
text-transform: uppercase;
}
h5, h6 {
text-transform: uppercase;
}
aside {
padding: 1em;
border: 1px solid $print-color-light;
border-radius: 5px;
margin-top: 1.5em;
margin-bottom: 1.5em;
line-height: 1.6;
}
aside:before {
vertical-align: middle;
padding-right: 0.5em;
font-size: 14px;
}
aside.notice:before {
@extend %icon-info-sign;
}
aside.warning:before {
@extend %icon-exclamation-sign;
}
aside.success:before {
@extend %icon-ok-sign;
}
}

616
api-docs-slate/source/stylesheets/screen.css.scss

@ -0,0 +1,616 @@
@charset "utf-8";
@import 'normalize';
@import 'variables';
@import 'icon-font';
/*
Copyright 2008-2013 Concur Technologies, Inc.
Licensed under the Apache License, Version 2.0 (the "License"); you may
not use this file except in compliance with the License. You may obtain
a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations
under the License.
*/
////////////////////////////////////////////////////////////////////////////////
// GENERAL STUFF
////////////////////////////////////////////////////////////////////////////////
html, body {
color: $main-text;
padding: 0;
margin: 0;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
@extend %default-font;
background-color: $main-bg;
height: 100%;
-webkit-text-size-adjust: none; /* Never autoresize text */
}
////////////////////////////////////////////////////////////////////////////////
// TABLE OF CONTENTS
////////////////////////////////////////////////////////////////////////////////
#toc > ul > li > a > span {
float: right;
background-color: #2484FF;
border-radius: 40px;
width: 20px;
}
.toc-wrapper {
transition: left 0.3s ease-in-out;
overflow-y: auto;
overflow-x: hidden;
position: fixed;
z-index: 30;
top: 0;
left: 0;
bottom: 0;
width: $nav-width;
background-color: $nav-bg;
font-size: 13px;
font-weight: bold;
// language selector for mobile devices
.lang-selector {
display: none;
a {
padding-top: 0.5em;
padding-bottom: 0.5em;
}
}
// This is the logo at the top of the ToC
&>img {
display: block;
max-width: 100%;
}
&>.search {
position: relative;
input {
background: $nav-bg;
border-width: 0 0 1px 0;
border-color: $search-box-border-color;
padding: 6px 0 6px 20px;
box-sizing: border-box;
margin: $nav-v-padding $nav-padding;
width: $nav-width - 30;
outline: none;
color: $nav-text;
border-radius: 0; /* ios has a default border radius */
}
&:before {
position: absolute;
top: 17px;
left: $nav-padding;
color: $nav-text;
@extend %icon-search;
}
}
.logo {
margin-bottom: $logo-margin;
}
.search-results {
margin-top: 0;
box-sizing: border-box;
height: 0;
overflow-y: auto;
overflow-x: hidden;
transition-property: height, margin;
transition-duration: 180ms;
transition-timing-function: ease-in-out;
background: $nav-subitem-bg;
&.visible {
height: 30%;
margin-bottom: 1em;
}
li {
margin: 1em $nav-padding;
line-height: 1;
}
a {
color: $nav-text;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
}
// The Table of Contents is composed of multiple nested
// unordered lists. These styles remove the default
// styling of an unordered list because it is ugly.
ul, li {
list-style: none;
margin: 0;
padding: 0;
line-height: 28px;
}
li {
color: $nav-text;
transition-property: background;
transition-timing-function: linear;
transition-duration: 200ms;
}
// This is the currently selected ToC entry
.toc-link.active {
background-color: $nav-active-bg;
color: $nav-active-text;
}
// this is parent links of the currently selected ToC entry
.toc-link.active-parent {
background-color: $nav-active-parent-bg;
color: $nav-active-parent-text;
}
.toc-list-h2 {
display: none;
background-color: $nav-subitem-bg;
font-weight: 500;
}
.toc-h2 {
padding-left: $nav-padding + $nav-indent;
font-size: 12px;
}
.toc-footer {
padding: 1em 0;
margin-top: 1em;
border-top: 1px dashed $nav-footer-border-color;
li,a {
color: $nav-text;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
li {
font-size: 0.8em;
line-height: 1.7;
text-decoration: none;
}
}
}
.toc-link, .toc-footer li {
padding: 0 $nav-padding 0 $nav-padding;
display: block;
overflow-x: hidden;
white-space: nowrap;
text-overflow: ellipsis;
text-decoration: none;
color: #fff;
transition-property: background;
transition-timing-function: linear;
transition-duration: 130ms;
}
// button to show navigation on mobile devices
#nav-button {
span {
display: block;
$side-pad: $main-padding / 2 - 8px;
padding: $side-pad $side-pad $side-pad;
background-color: rgba($main-bg, 0.7);
transform-origin: 0 0;
transform: rotate(-90deg) translate(-100%, 0);
border-radius: 0 0 0 5px;
}
padding: 0 1.5em 5em 0; // increase touch size area
display: none;
position: fixed;
top: 0;
left: 0;
z-index: 100;
color: #000;
text-decoration: none;
font-weight: bold;
opacity: 0.7;
line-height: 16px;
img {
height: 16px;
vertical-align: bottom;
}
transition: left 0.3s ease-in-out;
&:hover { opacity: 1; }
&.open {left: $nav-width}
}
////////////////////////////////////////////////////////////////////////////////
// PAGE LAYOUT AND CODE SAMPLE BACKGROUND
////////////////////////////////////////////////////////////////////////////////
.page-wrapper {
margin-left: $nav-width;
position: relative;
z-index: 10;
background-color: $main-bg;
min-height: 100%;
padding-bottom: 1px; // prevent margin overflow
// The dark box is what gives the code samples their dark background.
// It sits essentially under the actual content block, which has a
// transparent background.
// I know, it's hackish, but it's the simplist way to make the left
// half of the content always this background color.
.dark-box {
width: $examples-width;
background-color: $examples-bg;
position: absolute;
right: 0;
top: 0;
bottom: 0;
}
.lang-selector {
position: fixed;
z-index: 50;
border-bottom: 5px solid $lang-select-active-bg;
}
}
.lang-selector {
background-color: $lang-select-bg;
width: 100%;
font-weight: bold;
a {
display: block;
float:left;
color: $lang-select-text;
text-decoration: none;
padding: 0 10px;
line-height: 30px;
outline: 0;
&:active, &:focus {
background-color: $lang-select-pressed-bg;
color: $lang-select-pressed-text;
}
&.active {
background-color: $lang-select-active-bg;
color: $lang-select-active-text;
}
}
&:after {
content: '';
clear: both;
display: block;
}
}
////////////////////////////////////////////////////////////////////////////////
// CONTENT STYLES
////////////////////////////////////////////////////////////////////////////////
// This is all the stuff with the light background in the left half of the page
.content {
// fixes webkit rendering bug for some: see #538
-webkit-transform: translateZ(0);
// to place content above the dark box
position: relative;
z-index: 30;
&:after {
content: '';
display: block;
clear: both;
}
&>h1, &>h2, &>h3, &>h4, &>h5, &>h6, &>p, &>table, &>ul, &>ol, &>aside, &>dl {
margin-right: $examples-width;
padding: 0 $main-padding;
box-sizing: border-box;
display: block;
@extend %left-col;
}
&>ul, &>ol {
padding-left: $main-padding + 15px;
}
// the div is the tocify hidden div for placeholding stuff
&>h1, &>h2, &>div {
clear:both;
}
h1 {
@extend %header-font;
font-size: 25px;
padding-top: 0.5em;
padding-bottom: 0.5em;
margin-bottom: $h1-margin-bottom;
margin-top: 2em;
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background-color: #fdfdfd;
}
h1:first-child, div:first-child + h1 {
border-top-width: 0;
margin-top: 0;
}
h2 {
@extend %header-font;
font-size: 19px;
margin-top: 4em;
margin-bottom: 0;
border-top: 1px solid #ccc;
padding-top: 1.2em;
padding-bottom: 1.2em;
background-image: linear-gradient(to bottom, rgba(#fff, 0.2), rgba(#fff, 0));
}
// h2s right after h1s should bump right up
// against the h1s.
h1 + h2, h1 + div + h2 {
margin-top: $h1-margin-bottom * -1;
border-top: none;
}
h3, h4, h5, h6 {
@extend %header-font;
font-size: 15px;
margin-top: 2.5em;
margin-bottom: 0.8em;
}
h4, h5, h6 {
font-size: 10px;
}
hr {
margin: 2em 0;
border-top: 2px solid $examples-bg;
border-bottom: 2px solid $main-bg;
}
table {
margin-bottom: 1em;
overflow: auto;
th,td {
text-align: left;
vertical-align: top;
line-height: 1.6;
}
th {
padding: 5px 10px;
border-bottom: 1px solid #ccc;
vertical-align: bottom;
}
td {
padding: 10px;
}
tr:last-child {
border-bottom: 1px solid #ccc;
}
tr:nth-child(odd)>td {
background-color: lighten($main-bg,4.2%);
}
tr:nth-child(even)>td {
background-color: lighten($main-bg,2.4%);
}
}
dt {
font-weight: bold;
}
dd {
margin-left: 15px;
}
p, li, dt, dd {
line-height: 1.6;
margin-top: 0;
}
img {
max-width: 100%;
}
code {
background-color: rgba(0,0,0,0.05);
padding: 3px;
border-radius: 3px;
@extend %break-words;
@extend %code-font;
}
pre>code {
background-color: transparent;
padding: 0;
}
aside {
padding-top: 1em;
padding-bottom: 1em;
margin-top: 1.5em;
margin-bottom: 1.5em;
background: $aside-notice-bg;
line-height: 1.6;
&.warning {
background-color: $aside-warning-bg;
}
&.success {
background-color: $aside-success-bg;
}
}
aside:before {
vertical-align: middle;
padding-right: 0.5em;
font-size: 14px;
}
aside.notice:before {
@extend %icon-info-sign;
}
aside.warning:before {
@extend %icon-exclamation-sign;
}
aside.success:before {
@extend %icon-ok-sign;
}
.search-highlight {
padding: 2px;
margin: -2px;
border-radius: 4px;
border: 1px solid #F7E633;
background: linear-gradient(to top left, #F7E633 0%, #F1D32F 100%);
}
}
////////////////////////////////////////////////////////////////////////////////
// CODE SAMPLE STYLES
////////////////////////////////////////////////////////////////////////////////
// This is all the stuff that appears in the right half of the page
.content {
pre, blockquote {
background-color: $code-bg;
color: #fff;
margin: 0;
width: $examples-width;
float:right;
clear:right;
box-sizing: border-box;
@extend %right-col;
&>p { margin: 0; }
a {
color: #fff;
text-decoration: none;
border-bottom: dashed 1px #ccc;
}
}
pre {
@extend %code-font;
padding-top: 2em;
padding-bottom: 2em;
padding: 2em $main-padding;
}
blockquote {
&>p {
background-color: $code-annotation-bg;
padding: $code-annotation-padding 2em;
color: #eee;
}
}
}
////////////////////////////////////////////////////////////////////////////////
// RESPONSIVE DESIGN
////////////////////////////////////////////////////////////////////////////////
// These are the styles for phones and tablets
// There are also a couple styles disperesed
@media (max-width: $tablet-width) {
.toc-wrapper {
left: -$nav-width;
&.open {
left: 0;
}
}
.page-wrapper {
margin-left: 0;
}
#nav-button {
display: block;
}
.toc-link {
padding-top: 0.3em;
padding-bottom: 0.3em;
}
}
@media (max-width: $phone-width) {
.dark-box {
display: none;
}
%left-col {
margin-right: 0;
}
.toc-wrapper .lang-selector {
display: block;
}
.page-wrapper .lang-selector {
display: none;
}
%right-col {
width: auto;
float: none;
}
%right-col + %left-col {
margin-top: $main-padding;
}
}
.highlight .c, .highlight .cm, .highlight .c1, .highlight .cs {
color: #909090;
}
.highlight, .highlight .w {
background-color: $code-bg;
}
@import 'custom';

2
api-docs/index.html

@ -682,7 +682,7 @@
</li>
</div>
<ul class="toc-footer">
<li><a href='http://bcoin.io/slack-signup.html'>Join us on slack</a></li>
<li><a href='http://bcoin.io/slack-signup.html'>Join us on Slack</a></li>
<li><a href='https://github.com/bcoin-org/bcoin'>See the code on GitHub</a></li>
<li><a href='http://bcoin.io/guides.html'>Browse the guides</a></li>
<li><a href='http://bcoin.io/docs/index.html'>Full API Documentation</a></li>

6
build-api.sh

@ -0,0 +1,6 @@
#!/bin/sh
cd ./api-docs-slate
gem install bundler
bundle install
bundle exec middleman build --clean # build api docs
cp -RT ./build/ ../api-docs && rm -r ./build

22
guides.html

@ -262,6 +262,7 @@
<ul class="icons-list">
<!-- GUIDES-LIST -->
<li><a href="guides/working-with-txs.html">Working with transactions</a></li>
<li><a href="guides/wallets.html">Wallets and Accounts and Keys, Oh My!</a></li>
<li><a href="guides/scripting.html">Intro to Scripting</a></li>
<li><a href="guides/op_return.html">Store Data on the Blockchain</a></li>
<li><a href="guides/multisig-tx.html">Creating Multisignature Transactions</a></li>
@ -356,6 +357,27 @@
</div>
</div>
</article>
<article class="post format-image">
<div class="row">
<div class="col-sm-1"></div>
<!-- images not used yet
<div class="col-sm-3">
<div class="post-preview">
<a href="#"><img src="assets/images/guides/get-started.png" alt=""></a>
</div>
</div> -->
<div class="col-sm-10">
<div class="post-content" style="color:#000;">
<h2 class="post-title"><a href="guides/wallets.html">Wallets and Accounts and Keys, Oh My!</a></h2>
<ul class="post-meta">
<li>By Daniel McNally</li>
</ul>
<p>A guide to creating and working with wallets in bcoin</p>
<a href="guides/wallets.html" class="btn btn-lg btn-link btn-base">Start ›</a>
</div>
</div>
</div>
</article>
<article class="post format-image">
<div class="row">
<div class="col-sm-1"></div>

17
guides/crowdfund-tx.html

@ -267,6 +267,7 @@
<ul class="icons-list">
<!-- GUIDES-LIST -->
<li><a href="working-with-txs.html">Working with transactions</a></li>
<li><a href="wallets.html">Wallets and Accounts and Keys, Oh My!</a></li>
<li><a href="scripting.html">Intro to Scripting</a></li>
<li><a href="op_return.html">Store Data on the Blockchain</a></li>
<li><a href="multisig-tx.html">Creating Multisignature Transactions</a></li>
@ -317,7 +318,11 @@
<p>ALL|ANYONECANPAY<br>This construction can be used to make a &quot;crowdfunding”-style transaction. Someone attempting to raise funds can construct a transaction with a single output. The single output pays the &quot;goal&quot; amount to the fundraiser. Such a transaction is obviously not valid, as it has no inputs. However, others can now amend it by adding an input of their own, as a donation. They sign their own input with ALL|ANYONECANPAY. Unless enough inputs are gathered to reach the value of the output, the transaction is invalid. Each donation is a &quot;pledge,&quot; which cannot be collected by the fundraiser until the entire goal amount is raised.</p>
</blockquote>
<h2 id="the-code">The Code</h2><p>We&#39;ll walk through the steps of creating the transaction first without any wallet database or node running. Then we&#39;ll do the same thing using bcoin&#39;s walletdb to manage the keys to see how it would work in a more realistic application (skip to <a href="#version-2-using-the-bcoin-wallet-system">Version 2</a>) further in the guide to check it out). At the end, we&#39;ll put out some ideas of how these can be built upon for a more robust, production ready application. (If this is something you&#39;d be interested in building, <a href="http://bcoin.io/slack-signup.html">get in touch</a>!). If you want to see the code, checkout the <a href="https://github.com/Bucko13/bitcoin-fundraise">repo on github</a>.</p>
<<<<<<< HEAD
<p>If you&#39;re not comfortable with key management, coin selection, and how transactions are constructed, checkout the tutorial on <a href="http://bcoin.io/guides/working-with-txs.html">working with transactions</a> first.</p>
=======
<p>If you&#39;re not comfortable with key management, coin selection, and how transactions are constructed, checkout the tutorial on <a href="https://github.com/bcoin-org/bcoin/blob/master/docs/Working-with-transactions.md">working with transactions</a> first.</p>
>>>>>>> staging
<h3 id="version-1--manual-key-management">Version 1 - Manual Key Management</h3><h4 id="step-1-setup">Step 1: Setup</h4><p>Let&#39;s first start by importing the right tools, setting up some constants, and creating our keychains. (make sure you&#39;ve installed the latest version of bcoin into your project with <code>npm install bcoin</code>).</p>
<p>Note that we&#39;re setting the fundingTarget and amountToFund as constants for simplicity, but they could be set based on user input or some other variable circumstances.</p>
<pre class="snippet line-numbers language-javascript"><code class="line-numbers language-javascript"><span class="token string">'use strict'</span><span class="token punctuation">;</span>
@ -399,7 +404,11 @@
<span class="token punctuation">}</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token property">"1"</span><span class="token operator">:</span> <span class="token punctuation">[</span>...<span class="token punctuation">]</span>
<<<<<<< HEAD
<span class="token punctuation">}</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><h4 id="step-3-prepare-your-coins">Step 3: Prepare your Coins</h4><p>Above, we just funded our funder accounts with a single 5BTC outpoint. This means that the next transaction funded from these accounts can only use that one outpoint (or <em>coin</em>) as an input and send the remainder back as change. Remember, in Bitcoin the way you send funds is you fund a transaction with a full UTXO (in this case we only have one worth 5BTC available to our keychains) and then send the change back to yourself as an additional output. Since ALL|ANYONECANPAY transactions mean a fixed output, you can&#39;t add new change outputs without other signatures becoming invalid which means we need a coin available equal to the amount we want to contribute to the crowdfund.</p>
=======
<span class="token punctuation">}</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><h4 id="step-4-prepare-your-coins">Step 4: Prepare your Coins</h4><p>Above, we just funded our funder accounts with a single 5BTC outpoint. This means that the next transaction funded from these accounts can only use that one outpoint (or <em>coin</em>) as an input and send the remainder back as change. Remember, in Bitcoin the way you send funds is you fund a transaction with a full UTXO (in this case we only have one worth 5BTC available to our keychains) and then send the change back to yourself as an additional output. Since ALL|ANYONECANPAY transactions mean a fixed output, you can&#39;t add new change outputs without other signatures becoming invalid which means we need a coin available equal to the amount we want to contribute to the crowdfund.</p>
>>>>>>> staging
<p>So what we want to do is have each funder create a coin (UTXO) with the value of what they want to donate.</p>
<p>The first thing we need to do make this work is calculate what the input will be. In our examples we are assuming that the funders cover the fee. Since different keyrings can be using different transaction types of different sizes (p2sh, multisig, etc.), we need a utility to calculate how much the fee should be for that input and add that to the amount to fund with.</p>
<h5 id="utility-functions">Utility functions</h5><p>We&#39;ll need some utility functions to help us out. It&#39;s nice to split these out separate from our main operations since we&#39;ll actually be reusing some of the functionality.</p>
@ -500,7 +509,11 @@
...
<span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token property">"1"</span><span class="token operator">:</span> <span class="token punctuation">[</span>...<span class="token punctuation">]</span>
<<<<<<< HEAD
<span class="token punctuation">}</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><h4 id="step-4-construct-the-transaction">Step 4: Construct the Transaction</h4><p>Now that we&#39;ve got our tools and coins ready, we can start to build the transaction!</p>
=======
<span class="token punctuation">}</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><h4 id="step-6-construct-the-transaction">Step 6: Construct the Transaction</h4><p>Now that we&#39;ve got our tools and coins ready, we can start to build the transaction!</p>
>>>>>>> staging
<pre class="snippet line-numbers language-javascript"><code class="line-numbers language-javascript"><span class="token keyword">const</span> composeCrowdfund <span class="token operator">=</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">composeCrowdfund</span><span class="token punctuation">(</span>coins<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment" spellcheck="true">//...</span>
@ -687,7 +700,11 @@
<span class="token function">composeWalletCrowdfund</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span>myCrowdfundTx <span class="token operator">=</span><span class="token operator">></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Transaction broadcast: '</span><span class="token punctuation">,</span> myCrowdfundTx<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token keyword">catch</span><span class="token punctuation">(</span>e <span class="token operator">=</span><span class="token operator">></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'There was a problem: '</span><span class="token punctuation">,</span> e<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><p>And there you have it! If you were doing this on testnet, your <code>fundeeWallet</code> should now be 1BTC richer. If you&#39;re on a simnet or regtest network, you&#39;ll have to mine a block with your transactions to get those funds confirmed. Also note that, unless you have exact change coins, there will be 3 transactions that need to be confirmed: one each for the wallets that are splitting coins, and one for the crowdfund transaction.</p>
<<<<<<< HEAD
<h2 id="how-to-extend-and-improve">How to Extend and Improve</h2><p>These examples are obviously pretty basic, but they should give you an idea of how to use Bitcoin&#39;s scripting to build out the foundation for more complex applications. Here are some ideas on how you could build on top of these examples and get closer to a production ready application.</p>
=======
<h2 id="how-to-build-it-out">How to Build it Out</h2><p>These examples are obviously pretty basic, but they should give you an idea of how to use Bitcoin&#39;s scripting to build out the foundation for more complex applications. Here are some ideas on how you could build on top of these examples and get closer to a production ready application.</p>
>>>>>>> staging
<ul>
<li>More flexible contribution scheme (currently it&#39;s just 2 funders that split the amount evenly). E.g. custom number of contributers, custom contribution amount, etc.</li>
<li>UX to let people interact with the transaction via a browser</li>

1
guides/generate-address.html

@ -267,6 +267,7 @@
<ul class="icons-list">
<!-- GUIDES-LIST -->
<li><a href="working-with-txs.html">Working with transactions</a></li>
<li><a href="wallets.html">Wallets and Accounts and Keys, Oh My!</a></li>
<li><a href="scripting.html">Intro to Scripting</a></li>
<li><a href="op_return.html">Store Data on the Blockchain</a></li>
<li><a href="multisig-tx.html">Creating Multisignature Transactions</a></li>

3
guides/install-linux.html

@ -267,6 +267,9 @@
<ul class="icons-list">
<!-- GUIDES-LIST -->
<li><a href="working-with-txs.html">Working with transactions</a></li>
<li><a href="generate-address.html">Generate an Address</a></li>
<li><a href="crowdfund-tx.html">Creating a Crowdfunding Transaction</a></li>
<li><a href="scripting.html">Intro to Scripting</a></li>
<li><a href="op_return.html">Store Data on the Blockchain</a></li>
<li><a href="multisig-tx.html">Creating Multisignature Transactions</a></li>

1
guides/install-mac.html

@ -267,6 +267,7 @@
<ul class="icons-list">
<!-- GUIDES-LIST -->
<li><a href="working-with-txs.html">Working with transactions</a></li>
<li><a href="wallets.html">Wallets and Accounts and Keys, Oh My!</a></li>
<li><a href="scripting.html">Intro to Scripting</a></li>
<li><a href="op_return.html">Store Data on the Blockchain</a></li>
<li><a href="multisig-tx.html">Creating Multisignature Transactions</a></li>

1
guides/install-windows.html

@ -267,6 +267,7 @@
<ul class="icons-list">
<!-- GUIDES-LIST -->
<li><a href="working-with-txs.html">Working with transactions</a></li>
<li><a href="wallets.html">Wallets and Accounts and Keys, Oh My!</a></li>
<li><a href="scripting.html">Intro to Scripting</a></li>
<li><a href="op_return.html">Store Data on the Blockchain</a></li>
<li><a href="multisig-tx.html">Creating Multisignature Transactions</a></li>

1
guides/multisig-tx.html

@ -267,6 +267,7 @@
<ul class="icons-list">
<!-- GUIDES-LIST -->
<li><a href="working-with-txs.html">Working with transactions</a></li>
<li><a href="wallets.html">Wallets and Accounts and Keys, Oh My!</a></li>
<li><a href="scripting.html">Intro to Scripting</a></li>
<li><a href="op_return.html">Store Data on the Blockchain</a></li>
<li><a href="multisig-tx.html">Creating Multisignature Transactions</a></li>

2
guides/op_return.html

@ -267,12 +267,12 @@
<ul class="icons-list">
<!-- GUIDES-LIST -->
<li><a href="working-with-txs.html">Working with transactions</a></li>
<li><a href="wallets.html">Wallets and Accounts and Keys, Oh My!</a></li>
<li><a href="scripting.html">Intro to Scripting</a></li>
<li><a href="op_return.html">Store Data on the Blockchain</a></li>
<li><a href="multisig-tx.html">Creating Multisignature Transactions</a></li>
<li><a href="generate-address.html">Generate an Address</a></li>
<li><a href="crowdfund-tx.html">Create a Crowdfunding Transaction</a></li>
<li><a href="beginners.html">Beginners Guide to Getting Started</a></li>
<!-- /GUIDES-LIST -->
</ul>
</div>

2
guides/scripting.html

@ -267,12 +267,12 @@
<ul class="icons-list">
<!-- GUIDES-LIST -->
<li><a href="working-with-txs.html">Working with transactions</a></li>
<li><a href="wallets.html">Wallets and Accounts and Keys, Oh My!</a></li>
<li><a href="scripting.html">Intro to Scripting</a></li>
<li><a href="op_return.html">Store Data on the Blockchain</a></li>
<li><a href="multisig-tx.html">Creating Multisignature Transactions</a></li>
<li><a href="generate-address.html">Generate an Address</a></li>
<li><a href="crowdfund-tx.html">Create a Crowdfunding Transaction</a></li>
<li><a href="beginners.html">Beginners Guide to Getting Started</a></li>
<!-- /GUIDES-LIST -->
</ul>
</div>

699
guides/wallets.html

@ -0,0 +1,699 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="">
<title>bcoin | Extending Bitcoin into Enterprise & Production</title>
<!-- Favicons -->
<!-- old
<link rel="shortcut icon" href="../assets/images/bcoin-ico.png">-->
<!-- generated from http://www.favicon-generator.org/ -->
<link rel="apple-touch-icon" sizes="57x57" href="../assets/images/apple-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="../assets/images/apple-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="../assets/images/apple-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="../assets/images/apple-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="../assets/images/apple-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="../assets/images/apple-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="../assets/images/apple-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="../assets/images/apple-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="../assets/images/apple-icon-180x180.png">
<link rel="icon" type="image/png" sizes="192x192" href="../assets/images/android-icon-192x192.png">
<link rel="icon" type="image/png" sizes="32x32" href="../assets/images/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="../assets/images/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="../assets/images/favicon-16x16.png">
<link rel="manifest" href="../assets/images/manifest.json">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage" content="../assets/images/ms-icon-144x144.png">
<meta name="theme-color" content="#ffffff">
<!-- Web Fonts -->
<link href='http://fonts.googleapis.com/css?family=Open+Sans:300,400italic,400,600,700' rel='stylesheet'>
<link href='https://fonts.googleapis.com/css?family=Montserrat:700' rel='stylesheet' type='text/css'>
<!-- Bootstrap core CSS -->
<link href="../assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<!-- Code Snippet CSS -->
<link href="../assets/css/prism.css" rel="stylesheet">
<link href="../assets/css/custom.css" rel="stylesheet">
<!-- Icon Fonts -->
<link href="../assets/css/font-awesome.min.css" rel="stylesheet">
<link href="../assets/css/simple-line-icons.css" rel="stylesheet">
<!-- Plugins -->
<link href="../assets/css/magnific-popup.css" rel="stylesheet">
<link href="../assets/css/owl.carousel.css" rel="stylesheet">
<link href="../assets/css/flexslider.css" rel="stylesheet">
<link href="../assets/css/animate.min.css" rel="stylesheet">
<!-- Template core CSS -->
<link href="../assets/css/vertical.min.css" rel="stylesheet">
<link href="../assets/css/template.css" rel="stylesheet">
<!-- Google Analytics Tracking -->
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-96446060-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body>
<!-- PRELOADER -->
<div class="page-loader">
<div class="img-loader">Loading...
<!-- Bcoin logo in SVG -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 200 56" style="enable-background:new 0 0 200 56;" xml:space="preserve">
<g id="XMLID_108_">
<g id="XMLID_123_">
<path id="XMLID_124_" d="M8.4,51.8H3.2V4.2h5.2v19.2h0.8c1.2-2,2.8-3.6,4.8-4.7c2-1.1,4.3-1.6,6.7-1.6c2,0,4,0.4,5.8,1.2
c1.8,0.8,3.4,1.9,4.8,3.3c1.4,1.5,2.5,3.2,3.3,5.4s1.2,4.6,1.2,7.3v1.4c0,2.8-0.4,5.2-1.2,7.4c-0.8,2.1-1.9,3.9-3.3,5.4
c-1.4,1.5-3,2.6-4.9,3.3s-3.8,1.1-5.9,1.1c-1.1,0-2.2-0.1-3.3-0.4c-1.1-0.3-2.2-0.6-3.2-1.2c-1-0.5-1.9-1.2-2.8-1.9
c-0.8-0.7-1.6-1.6-2.1-2.7H8.4V51.8z M19.4,47.7c1.6,0,3.1-0.3,4.4-0.9c1.3-0.6,2.5-1.4,3.5-2.4c1-1,1.8-2.3,2.3-3.8
c0.6-1.5,0.8-3.2,0.8-5v-1.4c0-1.8-0.3-3.5-0.8-4.9c-0.6-1.5-1.3-2.7-2.3-3.8c-1-1.1-2.2-1.9-3.5-2.5c-1.4-0.6-2.8-0.9-4.4-0.9
c-1.6,0-3,0.3-4.3,0.9c-1.3,0.6-2.5,1.5-3.5,2.6c-1,1.1-1.8,2.4-2.4,3.9c-0.6,1.5-0.9,3.2-0.9,5v0.8c0,1.9,0.3,3.6,0.9,5.1
c0.6,1.5,1.4,2.8,2.4,3.9s2.2,1.9,3.5,2.5C16.4,47.4,17.9,47.7,19.4,47.7z"/>
</g>
<g id="XMLID_120_">
<path id="XMLID_121_" d="M76.1,39.8c-0.4,1.9-1,3.6-1.8,5.2c-0.9,1.6-2,3-3.3,4.1s-2.9,2.1-4.7,2.7c-1.8,0.6-3.8,1-5.9,1
c-2.3,0-4.5-0.4-6.6-1.2c-2.1-0.8-3.9-1.9-5.4-3.4c-1.6-1.5-2.8-3.3-3.7-5.4c-0.9-2.1-1.4-4.6-1.4-7.4v-0.8c0-2.7,0.5-5.2,1.4-7.4
c0.9-2.2,2.1-4,3.7-5.5c1.6-1.5,3.4-2.7,5.4-3.5c2.1-0.8,4.3-1.2,6.6-1.2c2.1,0,4,0.3,5.8,1c1.8,0.6,3.3,1.5,4.7,2.7
c1.4,1.2,2.5,2.5,3.3,4.1c0.9,1.6,1.5,3.3,1.8,5.2l-5.2,1.2c-0.1-1.2-0.5-2.3-1-3.4c-0.5-1.1-1.2-2.1-2.1-2.9
c-0.9-0.8-1.9-1.5-3.2-2c-1.2-0.5-2.7-0.7-4.3-0.7c-1.6,0-3.1,0.3-4.5,0.9c-1.4,0.6-2.6,1.5-3.7,2.6c-1.1,1.1-1.9,2.4-2.5,4
c-0.6,1.5-0.9,3.2-0.9,5v0.8c0,1.9,0.3,3.6,0.9,5.1c0.6,1.5,1.4,2.8,2.5,3.8c1.1,1,2.3,1.8,3.7,2.4c1.4,0.6,3,0.9,4.6,0.9
s3.1-0.3,4.3-0.8c1.2-0.5,2.3-1.2,3.1-2c0.9-0.8,1.6-1.8,2.1-2.9c0.5-1.1,0.9-2.2,1-3.4L76.1,39.8z"/>
</g>
<g id="XMLID_116_">
<path id="XMLID_117_" d="M117.2,35.4c0,2.8-0.5,5.3-1.4,7.5c-0.9,2.2-2.1,4-3.6,5.4c-1.5,1.5-3.3,2.6-5.3,3.4
c-2,0.8-4.1,1.2-6.3,1.2c-2.2,0-4.3-0.4-6.3-1.2c-2-0.8-3.8-1.9-5.3-3.4c-1.5-1.5-2.7-3.3-3.6-5.4c-0.9-2.2-1.4-4.6-1.4-7.5v-0.8
c0-2.8,0.5-5.2,1.4-7.4c0.9-2.2,2.1-4,3.7-5.5c1.5-1.5,3.3-2.6,5.3-3.4c2-0.8,4.1-1.2,6.3-1.2c2.2,0,4.3,0.4,6.3,1.2
c2,0.8,3.8,1.9,5.3,3.4c1.5,1.5,2.8,3.3,3.7,5.5c0.9,2.2,1.4,4.6,1.4,7.4V35.4z M100.6,47.7c1.6,0,3.1-0.3,4.4-0.9
c1.4-0.6,2.5-1.4,3.6-2.5c1-1.1,1.8-2.4,2.4-3.9c0.6-1.5,0.9-3.2,0.9-5.1v-0.8c0-1.8-0.3-3.5-0.9-5c-0.6-1.5-1.4-2.8-2.4-3.9
c-1-1.1-2.2-1.9-3.6-2.6c-1.4-0.6-2.8-0.9-4.4-0.9c-1.6,0-3,0.3-4.4,0.9c-1.4,0.6-2.6,1.5-3.6,2.6c-1,1.1-1.8,2.4-2.4,3.9
c-0.6,1.5-0.9,3.2-0.9,5v0.8c0,1.9,0.3,3.6,0.9,5.1c0.6,1.5,1.4,2.8,2.4,3.9c1,1.1,2.2,1.9,3.6,2.5C97.5,47.5,99,47.7,100.6,47.7z
"/>
</g>
<g id="XMLID_112_">
<path id="XMLID_113_" d="M127.6,46.9h11.6V23h-10.4v-4.9h15.6v28.9h10.8v4.9h-27.6V46.9z M137.1,8c0-1.3,0.5-2.4,1.4-3.4
c0.9-0.9,2-1.4,3.3-1.4c1.3,0,2.4,0.5,3.3,1.4c0.9,0.9,1.4,2.1,1.4,3.4c0,1.3-0.5,2.4-1.4,3.4c-0.9,0.9-2,1.4-3.3,1.4
c-1.3,0-2.4-0.5-3.3-1.4C137.5,10.4,137.1,9.3,137.1,8z"/>
</g>
<g id="XMLID_109_">
<path id="XMLID_110_" d="M172.8,51.8h-5.2V18.1h5.2v5.7h0.8c2-4.4,5.6-6.7,10.7-6.7c3.8,0,6.9,1.2,9.1,3.6
c2.3,2.4,3.4,6.1,3.4,10.9v20.2h-5.2V32.8c0-3.5-0.8-6.2-2.3-8c-1.6-1.8-3.7-2.7-6.3-2.7c-3.2,0-5.6,1.1-7.4,3.3s-2.7,5.1-2.7,8.8
V51.8z"/>
</g>
</g>
</svg>
</div>
</div>
<!-- END PRELOADER -->
<!-- HEADER -->
<header class="header js-stick">
<div class="container">
<!-- YOUR LOGO HERE -->
<div class="inner-header">
<a class="inner-brand" href="../index.html">
<img class="brand-light" src="../assets/images/logo-light.png" width="100" alt="">
<img class="brand-dark" src="../assets/images/logo-dark.png" width="100" alt="">
</a>
</div>
<!-- OPEN MOBILE MENU -->
<div class="main-nav-toggle">
<div class="nav-icon-toggle" data-toggle="collapse" data-target="#custom-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</div>
</div>
<!-- WIDGETS MENU -->
<div class="inner-header pull-right hide-me">
<div class="menu-extras clearfix">
<!-- SLACK LINK -->
<div class="menu-item">
<div class="">
<a href="../slack-signup.html" target="_blank" id="" data-toggle="tooltip" title="" data-placement="bottom" data-original-title="Join us on Slack!">
<img src="../assets/images/slack_icon.svg" width="18" height="18"/>
<span class=""></span>
</a>
</div>
</div>
<!-- STACK EXCHANGE LINK -->
<div class="menu-item">
<div class="">
<a href="https://bitcoin.stackexchange.com/questions/tagged/bcoin" target="_blank" id="" data-toggle="tooltip" title="" data-placement="bottom" data-original-title="Questions! Checkout Stack Exchange.">
<img src="../assets/images/stack-exchange-icon.svg" width="18" height="18"/>
<span class=""></span>
</a>
</div>
</div>
<!-- GITHUB STUFF -->
<div class="menu-item">
<div class="">
<a href="https://github.com/bcoin-org/bcoin" target="_blank" id="" data-toggle="tooltip" title="" data-placement="bottom" data-original-title="Visit bcoin on GitHub to see the code!">
<img src="../assets/images/github_icon.svg" width="18" height="18"/>
<span class=""></span>
</a>
</div>
</div>
<div class="menu-item">
<div class="ghbuttons">
<a class="github-button" href="https://github.com/bcoin-org/bcoin" data-icon="octicon-star" data-count-href="/bcoin-org/bcoin/stargazers" data-show-count="true" data-count-aria-label="# stargazers on GitHub" aria-label="Star bcoin-org/bcoin on GitHub">Star</a>
<a class="github-button" href="https://github.com/bcoin-org/bcoin/fork" data-icon="octicon-repo-forked" data-count-href="/bcoin-org/bcoin/network" data-show-count="true" data-count-aria-label="# forks on GitHub" aria-label="Fork bcoin-org/bcoin on GitHub">Fork</a>
</div>
</div>
</div>
</div>
<!-- MAIN MENU -->
<nav id="custom-collapse" class="main-nav collapse clearfix">
<ul class="inner-nav pull-right">
<!-- HOME -->
<li><a href="../index.html">Home</a></li>
<!-- END HOME -->
<!-- FEATURES -->
<li><a href="../index.html#features">What is Bcoin</a></li>
<!-- END FEATURES -->
<!-- GUIDES -->
<li><a href="../guides.html">Guides</a></li>
<!-- GUIDES -->
<!-- API REFERENCE - newer, how to interact once you're setup -->
<li><a href="../api-docs/index.html">API Docs</a></li>
<!-- END API -->
<!-- FULL DOCS - older, full reference
<li><a href="http://bcoin.io/docs/index.html">Docs</a></li> -->
<!-- END DOCS -->
<!-- DIVIDER
<li><a>&nbsp;</a></li>
<li><a href="#">All Demos</a></li>-->
</ul>
</nav>
</div>
</header>
<!-- END HEADER -->
<!-- WRAPPER -->
<div class="wrapper">
<!-- PAGE TITLE -->
<section class="module-sm bg-white-dark" data-background="../assets/images/bg-header.jpg">
<div class="container">
<div class="row">
<div class="col-sm-12 text-center">
<h2 class="montserrat text-uppercase m-b-10"><span class="text-highlight-black" style="line-height: 1.5;">&nbsp;Guides &nbsp;and &nbsp;Videos&nbsp;</span></h2>
</div>
</div>
</div>
</section>
<!-- END PAGE TITLE -->
<!-- GUIDES/TUTORIALS -->
<section class="module" style="padding-top:70px !important;">
<div class="container">
<div class="row">
<!-- START SIDEBAR -->
<div class="col-sm-3 sidebar">
<!-- CATEGORIES WIDGET -->
<div class="widget guide-list">
<h6 class="montserrat text-uppercase bottom-line">Install</h6>
<ul class="icons-list">
<!-- INSTALL-LIST -->
<li><a href="install-windows.html">Install on Windows (Video)</a></li>
<li><a href="install-mac.html">Install on Mac OS (Video)</a></li>
<li><a href="install-linux.html">Install on Linux (Video)</a></li>
<!-- /INSTALL-LIST -->
</ul>
<br>
<h6 class="montserrat text-uppercase bottom-line">Guides</h6>
<ul class="icons-list">
<!-- GUIDES-LIST -->
<li><a href="working-with-txs.html">Working with transactions</a></li>
<li><a href="wallets.html">Wallets and Accounts and Keys, Oh My!</a></li>
<li><a href="scripting.html">Intro to Scripting</a></li>
<li><a href="op_return.html">Store Data on the Blockchain</a></li>
<li><a href="multisig-tx.html">Creating Multisignature Transactions</a></li>
<li><a href="generate-address.html">Generate an Address</a></li>
<li><a href="crowdfund-tx.html">Create a Crowdfunding Transaction</a></li>
<!-- /GUIDES-LIST -->
</ul>
</div>
<!-- END CATEGORIES WIDGET -->
<!-- TEXT WIDGET -->
<div class="widget">
<h6 class="montserrat text-uppercase bottom-line">Looking for Docs?</h6>
<p>Checkout our <a href="../api-docs/index.html">API Docs</a> or the <a href="http://bcoin.io/docs/index.html">Full Documentation</a></p>
</div>
<!-- END TEXT WIDGET -->
<!-- TEXT WIDGET -->
<div class="widget">
<h6 class="montserrat text-uppercase bottom-line">Get Involved</h6>
<p>If you think you've got what it takes to make your own bcoin guides and tutorials, head on over to our <a href="https://github.com/bcoin-org/bcoin-org.github.io">GitHub repo</a> to see how you can make a request or contribute your own and earn bounties! You can also reach out to us on <a href="../slack-signup.html"> Slack.</a></p>
<p>Want to join the team?<a href="https://angel.co/purse/jobs/90956-bitcoin-protocol-engineer-bcoin"> We’re hiring.</a></p>
</div>
<!-- END TEXT WIDGET -->
</div>
<!-- END SIDEBAR -->
<!-- START OF ARTICLE CONTAINER -->
<div class="col-sm-9 blog-content post-thumbnail">
<!-- POST IMAGE -->
<article class="post format-image">
<div class="row">
<!--<div class="col-sm-5">
<div class="post-preview">
<a href="#"><img src="../assets/images/guides/get-started.png" alt=""></a>
</div>
</div>-->
<!-- after re-enabling the above code, change the col-sm below to col-sm-7 -->
<div class="panel-group">
<div class="col-sm-12 panel panel-default">
<div class="post-content" style="color:#000;">
<!-- START OF GUIDE -->
<h2 class="post-title panel-title" id="wallets-and-accounts-and-keys-oh-my!">Wallets and Accounts and Keys, Oh My!</h2><ul class="post-meta"><li class="author">By Daniel McNally</li></ul><p>Bcoin offers a powerful, modular way to create and manage bitcoin wallets. In this guide, I&#39;ll walk you through the concepts and features you&#39;ll need to know about to get started.</p>
<h2 id="the-basics">The Basics</h2><p>If you&#39;re a seasoned bitcoiner, you can probably skim this section or skip straight ahead to the <a href="#examples">Examples</a> section. But if you&#39;re relatively new or just want a refresher, this section will help you understand how wallets actually work. </p>
<h3 id="wallets">Wallets</h3><p>In the most basic sense, a bitcoin wallet is data that enables you to receive and spend bitcoins. Wallets come in <a href="https://www.coindesk.com/information/how-to-store-your-bitcoins/">many different types and designs</a>, and assessing all the options can be overwhelming. Fortunately, bcoin implements the latest specifications for structuring wallets that are easy to backup, easy to restore, and that work just as well for a bitcoin novice making their first transactions as for a business with millions of users depositing and withdrawing bitcoin.</p>
<h4 id="keys-to-the-game">Keys to the Game</h4><p>If you want to transact with bitcoin, you&#39;ll need keys. Each bitcoin address is associated with a particular key, and wallets are made up of many different keys. Keys consist of both a private key and a public key. The private key is required for spending and is extremely sensitive information, while a public key can be used to receive bitcoins and monitor a particular address. If you want to learn more about how this works, read up on <a href="https://en.wikipedia.org/wiki/Public-key_cryptography">Public-Key Cryptography</a>.</p>
<h4 id="hd-vs-non-hd,-you-mean-like-tvs?">HD vs. Non-HD, you mean like TVs?</h4><p>You may have seen references to &quot;HD&quot; wallets and wondered what that means. HD in this context does not mean &quot;high definition,&quot; as I assumed it did at first, but rather &quot;hierarchical deterministic.&quot; An HD wallet takes a <em>hierarchy</em> of keys in order and makes it so any key in that sequence can be <em>determined</em> by the one before it. This means that if you can produce the first key in the hierarchy, you can then generate a practically unlimited number of subsequent keys. The specification for HD wallets as implemented in bcoin is defined by <a href="https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki">Bitcoin Improvement Proposal (BIP) 32</a>.</p>
<p>Non-HD wallets, on the other hand, contain keys that are unrelated to one another. Backing up such a wallet means each key must be preserved individually. Not only is this more cumbersome, but it means that backups can quickly become out of date as new keys are added to the wallet. With an HD wallet, as long as you hold on to the seed - the data needed to recreate the first key - you will be able to recover every other key.</p>
<p>While bcoin uses HD wallets, it does allow you to import individual keys into a wallet. This can be a handy feature in certain cases, but it means you&#39;ll need to backup any imported keys separately as they will not be recoverable simply by using your seed.</p>
<p>But what exactly is the seed for an HD wallet? It can come in several forms, but bcoin implements <a href="https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki">BIP39</a> which enables seeds to be represented by a mnemonic made up of a fixed set of common words. This means your seed can be easily spoken, written down, or perhaps even memorized. But be careful! Your seed can be used to recover and spend everything in your HD wallet (except for the aforementioned imported keys), so treat it like you would an actual wallet with cash in it.</p>
<p>By default, mnemonics in bcoin are made up of twelve words representing 128 bits of entropy. This is a common standard that is far and away beyond what cutting edge computers can hope to crack via <a href="https://en.wikipedia.org/wiki/Brute-force_attack">brute force</a>. But if you want additional entropy, bcoin supports up to 512 bits of entropy which makes a 48 word mnemonic.</p>
<h3 id="accounts">Accounts</h3><p>Wallets in bcoin are partitioned into accounts. When you first create a wallet, a &quot;default&quot; account is created automatically along with it. Accounts can be used to track and manage separate sets of keys all within a single wallet. For example, a business can use accounts to generate distinct addresses for depositors or to segregate customer funds internally. </p>
<p>Bcoin implements <a href="https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki">BIP44</a> as a method of generating unlimited accounts deterministically. This adds additional dimensions to the hierarchy described above, meaning the same seed that can recover all your keys can also recover all your addresses.</p>
<p>Each account also comes with its own &quot;extended public key,&quot; a piece of data that can be used to generate all public keys for that account in deterministic fashion. This means, for instance, that a business can create limitless deposit addresses for its users without having to touch its critical private keys or seed. Remember that public keys can be used for receiving bitcoins, but not for spending, so a public key falling into the wrong hands will not immediately result in theft. </p>
<h3 id="watch-only-wallets">Watch Only Wallets</h3><p>Speaking of not touching private keys, bcoin gives you the option to create wallets that are &quot;watch only.&quot; Watch only wallets don&#39;t contain <em>any</em> private keys, which means they can&#39;t be used to spend the bitcoins they receive. However, they work perfectly fine for creating addresses, receiving bitcoins, and detecting incoming transactions. Using watch only wallets where appropriate reduces the risk of your keys and bitcoin being stolen and is good security practice.</p>
<p>Accounts always inherit the watch only behavior of their parent wallet. In other words, a watch only wallet will have exclusively watch only accounts while a regular wallet will have only regular accounts. Accordingly, you can&#39;t import private keys into a watch only wallet or public keys into regular wallets. If you try to mix and match watch only wallets and keys with bcoin, you&#39;re gonna have a bad time.</p>
<pre class="snippet line-numbers language-bash"><code class="line-numbers language-bash">~$ curl http://127.0.0.1:18332/wallet/watchonlywallet/import -X POST -d <span class="token string">'{"account":"default"
,"privateKey":"cNZfR3NhQ9oCP3pTjvPZETUuTW
Zo2k6EXtfczvbWyv7FdjMhppvJ"}'</span>
<span class="token punctuation">{</span>
<span class="token string">"error"</span><span class="token keyword">:</span> <span class="token punctuation">{</span>
<span class="token string">"type"</span><span class="token keyword">:</span> <span class="token string">"Error"</span>,
<span class="token string">"message"</span><span class="token keyword">:</span> <span class="token string">"Cannot import privkey into watch-only wallet."</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
~$ curl http://127.0.0.1:18332/wallet/privatekeywallet/import -X POST -d <span class="token string">'{"account":"default","publicKey":"02f4f200cb9391f8bbcc0a35e1f654b9b993b214a04ae7efd0313f4d4bf3d95745"}'</span><span class="token punctuation">{</span>
<span class="token string">"error"</span><span class="token keyword">:</span> <span class="token punctuation">{</span>
<span class="token string">"type"</span><span class="token keyword">:</span> <span class="token string">"Error"</span>,
<span class="token string">"message"</span><span class="token keyword">:</span> <span class="token string">"Cannot import pubkey into non watch-only wallet."</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><h3 id="api-authentication">API Authentication</h3><p>Bcoin can run as a server and allow you to interact with your wallets via a <a href="http://bcoin.io/api-docs/index.html?shell--curl#wallet">REST API</a>. It also allows you protect wallets from unauthenticated requests by running the server with the <code>wallet-auth</code> option. Each wallet you create has a <code>token</code> value that must be passed in with each request. Tokens, like accounts and keys, can also be deterministically generated using your HD seed. This means you can change the token on a wallet as often as you&#39;d like.</p>
<h3 id="recovery">Recovery</h3><p>By using the HD standards mentioned above, bcoin allows one to easily restore or transfer their entire wallet to different wallet implementations. By providing just the mnemonic, one can fully recover their wallet to a fresh instance of bcoin or any other software that properly implements BIP33, BIP39, and BIP44, like the <a href="https://trezor.io/">Trezor</a> hardware wallet.</p>
<h2 id="examples">Examples</h2><p>Enough chit chat, let&#39;s get down to business on how to create wallets, accounts, and keys with bcoin.</p>
<h3 id="nodejs">Node.js</h3><p>Below is a demo using javascript to instantiate a wallet and output important data and keys. Since bcoin is modular, you can easily use just the wallet functionality as I&#39;ve done here.</p>
<h4 id="setup">Setup</h4><p>With the <a href="https://www.npmjs.com/package/bcoin">bcoin package</a> installed, we&#39;ll first import bcoin and open a wallet database in memory.</p>
<pre class="snippet line-numbers language-javascript"><code class="line-numbers language-javascript"><span class="token comment" spellcheck="true">//import the bcoin module and set it to testnet</span>
<span class="token keyword">const</span> bcoin <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'bcoin'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">set</span><span class="token punctuation">(</span><span class="token string">'testnet'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> WalletDB <span class="token operator">=</span> bcoin<span class="token punctuation">.</span>walletdb<span class="token punctuation">;</span>
<span class="token keyword">const</span> WalletKey <span class="token operator">=</span> bcoin<span class="token punctuation">.</span>walletkey<span class="token punctuation">;</span>
<span class="token keyword">const</span> KeyRing <span class="token operator">=</span> bcoin<span class="token punctuation">.</span>keyring<span class="token punctuation">;</span>
<span class="token keyword">const</span> Mnemonic <span class="token operator">=</span> bcoin<span class="token punctuation">.</span>hd<span class="token punctuation">.</span>Mnemonic<span class="token punctuation">;</span>
<span class="token keyword">const</span> HD <span class="token operator">=</span> bcoin<span class="token punctuation">.</span>hd<span class="token punctuation">;</span>
<span class="token function">walletExample</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">catch</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>error<span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span>console<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">walletExample</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment" spellcheck="true">//for demonstration purposes, we'll be creating a temporary wallet in memory</span>
<span class="token keyword">const</span> wdb <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">WalletDB</span><span class="token punctuation">(</span><span class="token punctuation">{</span> db<span class="token punctuation">:</span> <span class="token string">'memory'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">await</span> wdb<span class="token punctuation">.</span><span class="token function">open</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><h4 id="creating-a-wallet">Creating a Wallet</h4><p>Creating a wallet in our database takes only one line.</p>
<pre class="snippet line-numbers language-javascript"><code class="line-numbers language-javascript"><span class="token comment" spellcheck="true">//creates and returns a Wallet object from scratch using a random master key and default options</span>
<span class="token keyword">const</span> wallet <span class="token operator">=</span> <span class="token keyword">await</span> wdb<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>wallet<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">/*{
wid: 2,
id: 'WLTdx4aYEPmmrQiYNwPop4nLtbpTEdJYwrN4',
network: 'testnet',
initialized: true,
accountDepth: 1,
token: 'eeae267e99d112793b892a8e30f89b1e1e0ba0d4984c2e6f09fc7931e750af5a', //the token you'll need to use the REST API with `wallet-auth` set to true
tokenDepth: 0,
state:
{ wid: undefined,
id: undefined,
tx: 0,
coin: 0,
unconfirmed: 0,
confirmed: 0 },
master:
{ encrypted: false,
key: { xprivkey: 'tprv8ZgxMBicQKsPdcD55gci7HBednWRaosU4CkAHNEAs3kAAj9m8TVrEzxAW3EPrTrFevVssHCCoRsA37vB65SUZs727k45Nz1Cjmy4tyaSFeR' }, //the keys to the castle, guard this carefully!
mnemonic:
{ bits: 128,
language: 'english',
entropy: '04a50a56fbaaadc26a2b1690ec74243f',
phrase: 'again choose noble warrior print thrive post glare movie glove animal legal', //the keys to the castle in human readable form
passphrase: '' } },
account:
{ wid: 2,
name: 'default',
network: &lt;Network: testnet>,
initialized: true,
witness: false,
watchOnly: false,
type: 'pubkeyhash',
m: 1,
n: 1,
accountIndex: 0,
receiveDepth: 1,
changeDepth: 1,
nestedDepth: 0,
lookahead: 10,
address: &lt;Address: type=pubkeyhash version=-1 str=mhNHETXFKDk7ZpGg3iEZb7guWZ2fbCuFjv>,
nestedAddress: null,
accountKey: 'tpubDDZ1r85SUsur87eW6uCrWancnCVHSLf5YcXzudCF6qBUQguR8upC6pgSuzxahDkf75SQ4LJ3R4x5NvfgQPmNjxhg2pcHzBCKcG2fBUQJ5U5', //the extended public key that can be used to generate receiving addresses for this account
keys: [] }
}*/</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><h4 id="creating-accounts-and-receiving-addresses">Creating Accounts and Receiving Addresses</h4><p>You can start generating addresses with our first account right away.</p>
<pre class="snippet line-numbers language-javascript"><code class="line-numbers language-javascript"><span class="token keyword">const</span> account <span class="token operator">=</span> <span class="token keyword">await</span> wallet<span class="token punctuation">.</span><span class="token function">getAccount</span><span class="token punctuation">(</span><span class="token string">'default'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">//now we have a wallet and default account, let's get our first and current receiving address</span>
<span class="token keyword">const</span> key0 <span class="token operator">=</span> account<span class="token punctuation">.</span><span class="token function">getAddress</span><span class="token punctuation">(</span><span class="token string">'string'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">//this will be the same value as seen in the 'address' property under 'account' in our wallet above</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>key0<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">//mhNHETXFKDk7ZpGg3iEZb7guWZ2fbCuFjv</span>
<span class="token comment" spellcheck="true">//we can skip ahead if we want, grabbing the hundredth key in the heirarchy like so</span>
<span class="token keyword">const</span> key100 <span class="token operator">=</span> account<span class="token punctuation">.</span><span class="token function">deriveReceive</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">//ok, technically this is the hundred-and-first key because the sequence is zero-based</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>key100<span class="token punctuation">.</span><span class="token function">getAddress</span><span class="token punctuation">(</span><span class="token string">'string'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">//mjVdQqQYWBpE6YzKyMRd96LxCMoJyeTX2i</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><p>You can also create a second account with a custom name.</p>
<pre class="snippet line-numbers language-javascript"><code class="line-numbers language-javascript"><span class="token comment" spellcheck="true">// let's create another account for hypothetical customer John Doe</span>
<span class="token keyword">const</span> jdAccount <span class="token operator">=</span> <span class="token keyword">await</span> wallet<span class="token punctuation">.</span><span class="token function">createAccount</span><span class="token punctuation">(</span><span class="token punctuation">{</span>name<span class="token punctuation">:</span> <span class="token string">'john_doe'</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>jdAccount<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">/*{
wid: 2,
name: '1',
network: &lt;Network: testnet>,
initialized: true,
witness: false,
watchOnly: false,
type: 'pubkeyhash',
m: 1,
n: 1,
accountIndex: 1,
receiveDepth: 1,
changeDepth: 1,
nestedDepth: 0,
lookahead: 10,
address: &lt;Address: type=pubkeyhash version=-1 str=muCSbWC6z1tAr2i1M5BKPWEZ8zapzcKfKh>,
nestedAddress: null,
accountKey: 'tpubDDZ1r85SUsur9txJF5ziLRD6757E1Q7x6VLfPby4YKqAdNwgmrkXBNDzMowxYJVoAizd7CCLHELY5X2HYzh6YurbH9vMyQJN
T92n87z22yX',
keys: []
}*/</span>
<span class="token comment" spellcheck="true">//Mr. Doe wants to make 10 deposits, let's get him a unique address for each one</span>
<span class="token keyword">const</span> depositAddressesToPrint <span class="token operator">=</span> <span class="token number">10</span><span class="token punctuation">;</span>
<span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">var</span> i<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">;</span> i<span class="token operator">&lt;</span>depositAddressesToPrint<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>jdAccount<span class="token punctuation">.</span><span class="token function">deriveReceive</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getAddress</span><span class="token punctuation">(</span><span class="token string">'string'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment" spellcheck="true">/*
muCSbWC6z1tAr2i1M5BKPWEZ8zapzcKfKh
n4TWmQyPQ8mAr2oEfbBzKF8Dw6LXXBidYJ
ms1jRu71BvEsJ4K3dMFrKFUnB8axZQdmSq
mn8xFgB68RjWGdKPVb8Up4P4v5MyqPoEQj
mzfXXKRXJBjTGRFrrg4wm1XPsdU9TLoN6T
n36TShvFCDaWgCMHHszUGiczA7Tcru4AQp
mnZBaquULuUhtwwxKTuxWNF7ZDMDNxScJd
mfpwjevu3FY4ZsWPd31J9oBH1qrxZLF1tH
mhTrDspHReXThUmMeo8dVJHqhkyHG8VPZ1
mxKo27kJpNazq9Q3cQ7458k2S2vcQar9Pd
*/</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><h4 id="getting-private-keys">Getting Private Keys</h4><p>Bcoin handles your private keys automatically for things like sending transactions and signing messages, but you can also manually extract private keys from a wallet.</p>
<pre class="snippet line-numbers language-javascript"><code class="line-numbers language-javascript"><span class="token comment" spellcheck="true">//the keys above are only good for receiving bitcoins, not spending them</span>
<span class="token comment" spellcheck="true">//let's get the extended private key for John Doe's account, which can be used to generate every private key for the account</span>
<span class="token keyword">const</span> jdExtendedPrivateKey <span class="token operator">=</span> wallet<span class="token punctuation">.</span>master<span class="token punctuation">.</span>key<span class="token punctuation">.</span><span class="token function">deriveAccount</span><span class="token punctuation">(</span><span class="token number">44</span><span class="token punctuation">,</span> jdAccount<span class="token punctuation">.</span>accountIndex<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">//44 is the fixed purpose for bip44 accounts </span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>jdExtendedPrivateKey<span class="token punctuation">.</span><span class="token function">xprivkey</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">//tprv8gryhi3CLWEBGRvWMSL7w1YyY3bHr4w3XBjt75vm842mntgv9Tvvzsc8Bf3NZt13ydD5QZaJVShMudE33egMhSLnEM41t5UUhRj5wA5u8Sc</span>
<span class="token comment" spellcheck="true">//for good measure, let's get the private key for John's first receiving address</span>
<span class="token keyword">const</span> branch <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">//the branch for receiving addresses</span>
<span class="token keyword">const</span> index <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">//index of 0 means the first key among the receiving addresses</span>
<span class="token keyword">const</span> jdPrivateKey0 <span class="token operator">=</span> jdExtendedPrivateKey<span class="token punctuation">.</span><span class="token function">derive</span><span class="token punctuation">(</span>branch<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">derive</span><span class="token punctuation">(</span>index<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> jdWalletKey0 <span class="token operator">=</span> WalletKey<span class="token punctuation">.</span><span class="token function">fromHD</span><span class="token punctuation">(</span>jdAccount<span class="token punctuation">,</span> jdPrivateKey0<span class="token punctuation">,</span> branch<span class="token punctuation">,</span> index<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">//the private key below can be imported into almost any bitcoin wallet, HD or non-HD, and used to spend coins from the corresponding address</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>jdWalletKey0<span class="token punctuation">.</span><span class="token function">getPrivateKey</span><span class="token punctuation">(</span><span class="token string">'base58'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">//cNZfR3NhQ9oCP3pTjvPZETUuTWZo2k6EXtfczvbWyv7FdjMhppvJ</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><h4 id="generating-mnemonics-and-recovering-keys">Generating Mnemonics and Recovering Keys</h4><p>Finally, you can create mnemonics manually and seed new wallets with them. And if you need to generate keys from a mnemonic you provide - either by recreating a wallet or by extracting specific keys - you can do that as well.</p>
<pre class="snippet line-numbers language-javascript"><code class="line-numbers language-javascript"><span class="token comment" spellcheck="true">//can wegenerate a mnemonic with twice as many bits of entropy to future proof against brute force attacks from the next millenium? sure we can.</span>
<span class="token keyword">const</span> mnemonic24 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Mnemonic</span><span class="token punctuation">(</span><span class="token punctuation">{</span>bits<span class="token punctuation">:</span> <span class="token number">256</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>mnemonic24<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">//page unknown ladder thunder airport merry run ball inject clinic danger valley equip consider normal twist casual duck essay almost trade regular two segment</span>
<span class="token comment" spellcheck="true">//what if we need to recover the wallet we've created above? no problem.</span>
<span class="token keyword">const</span> mnemonic <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Mnemonic</span><span class="token punctuation">(</span><span class="token string">'again choose noble warrior print thrive post glare movie glove animal legal'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> masterKey <span class="token operator">=</span> HD<span class="token punctuation">.</span><span class="token function">fromMnemonic</span><span class="token punctuation">(</span>mnemonic<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">//this wallet will generate all the same accounts, keys, addresses, and tokens if swapped in for the 'wallet' variable in examples above</span>
<span class="token keyword">const</span> recoveredWallet <span class="token operator">=</span> <span class="token keyword">await</span> wdb<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">{</span>master<span class="token punctuation">:</span> masterKey<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">//we can also recover only the keys for John Doe's first receiving address without recreating the wallet or account</span>
<span class="token comment" spellcheck="true">//this time we'll skip instantiating the account and use the BIP44 path for the second account, first branch, and first index on bitcoin testnet</span>
<span class="token keyword">const</span> jdRecoveredPrivateKey <span class="token operator">=</span> masterKey<span class="token punctuation">.</span><span class="token function">derivePath</span><span class="token punctuation">(</span><span class="token string">"m/44'/1'/1'/0/0"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> jdKeyRing <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">KeyRing</span><span class="token punctuation">(</span>jdRecoveredPrivateKey<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">//our output should be the same as what we logged to the console earlier in this example</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>jdKeyRing<span class="token punctuation">.</span><span class="token function">getAddress</span><span class="token punctuation">(</span><span class="token string">'string'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">//muCSbWC6z1tAr2i1M5BKPWEZ8zapzcKfKh</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>jdKeyRing<span class="token punctuation">.</span><span class="token function">getPrivateKey</span><span class="token punctuation">(</span><span class="token string">'base58'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">//cNZfR3NhQ9oCP3pTjvPZETUuTWZo2k6EXtfczvbWyv7FdjMhppvJ</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><h3 id="command-line-examples-against-a-local-bcoin-server">Command Line Examples against a Local bcoin Server</h3><p>If you already have bcoin <a href="https://github.com/bcoin-org/bcoin/wiki/Beginner&#39;s-Guide">set up as a full node</a>, you can use the command line to create wallets and demonstrate some of the topics I discussed in this guide. My examples below are against a running testnet bcoin instance with <code>wallet-auth</code> set to true.</p>
<pre class="snippet line-numbers language-bash"><code class="line-numbers language-bash">~$ bcoin wallet create guide1
<span class="token punctuation">{</span>
<span class="token string">"network"</span><span class="token keyword">:</span> <span class="token string">"testnet"</span>,
<span class="token string">"wid"</span><span class="token keyword">:</span> 2,
<span class="token string">"id"</span><span class="token keyword">:</span> <span class="token string">"guide1"</span>,
<span class="token string">"initialized"</span><span class="token keyword">:</span> true,
<span class="token string">"watchOnly"</span><span class="token keyword">:</span> false,
<span class="token string">"accountDepth"</span><span class="token keyword">:</span> 1,
<span class="token string">"token"</span><span class="token keyword">:</span> <span class="token string">"c88bc2fda2f265bc00c8fd28771c62695dbbddfd05ef2510f9e0afbec14818ba"</span>,
<span class="token string">"tokenDepth"</span><span class="token keyword">:</span> 0,
<span class="token string">"state"</span><span class="token keyword">:</span> <span class="token punctuation">{</span>
<span class="token string">"tx"</span><span class="token keyword">:</span> 0,
<span class="token string">"coin"</span><span class="token keyword">:</span> 0,
<span class="token string">"unconfirmed"</span><span class="token keyword">:</span> 0,
<span class="token string">"confirmed"</span><span class="token keyword">:</span> 0
<span class="token punctuation">}</span>,
<span class="token string">"master"</span><span class="token keyword">:</span> <span class="token punctuation">{</span>
<span class="token string">"encrypted"</span><span class="token keyword">:</span> <span class="token boolean">false</span>
<span class="token punctuation">}</span>,
<span class="token string">"account"</span><span class="token keyword">:</span> <span class="token punctuation">{</span>
<span class="token string">"name"</span><span class="token keyword">:</span> <span class="token string">"default"</span>,
<span class="token string">"initialized"</span><span class="token keyword">:</span> true,
<span class="token string">"witness"</span><span class="token keyword">:</span> false,
<span class="token string">"watchOnly"</span><span class="token keyword">:</span> false,
<span class="token string">"type"</span><span class="token keyword">:</span> <span class="token string">"pubkeyhash"</span>,
<span class="token string">"m"</span><span class="token keyword">:</span> 1,
<span class="token string">"n"</span><span class="token keyword">:</span> 1,
<span class="token string">"accountIndex"</span><span class="token keyword">:</span> 0,
<span class="token string">"receiveDepth"</span><span class="token keyword">:</span> 1,
<span class="token string">"changeDepth"</span><span class="token keyword">:</span> 1,
<span class="token string">"nestedDepth"</span><span class="token keyword">:</span> 0,
<span class="token string">"lookahead"</span><span class="token keyword">:</span> 10,
<span class="token string">"receiveAddress"</span><span class="token keyword">:</span> <span class="token string">"mirZQBLNFsjgxRC6STfCJU71nXqSon9U17"</span>,
<span class="token string">"nestedAddress"</span><span class="token keyword">:</span> null,
<span class="token string">"changeAddress"</span><span class="token keyword">:</span> <span class="token string">"n3qdAvsVk7v4q4CAp25SSPsfcBARJexSUr"</span>,
<span class="token string">"accountKey"</span><span class="token keyword">:</span> <span class="token string">"tpubDCsPHK6xw9CziuN6o7tk1rubLopp5ipy4rDsapkA12KYdcuLXNH7frWUcWsMiFjU5Jxqp2d37SidfmvAahsLqon14wXtor7uQvjLZscb2fh"</span>,
<span class="token string">"keys"</span><span class="token keyword">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><h4 id="auth-tokens">Auth Tokens</h4><p>See that <code>token</code>? We&#39;ll be needing that. With the token, we can do things like query our wallet balance.</p>
<pre class="snippet line-numbers language-bash"><code class="line-numbers language-bash">~$ bcoin wallet balance --id guide1 --token c88bc2fda2f265bc00c8fd28771c62695d
bbddfd05ef2510f9e0afbec14818ba
<span class="token punctuation">{</span>
<span class="token string">"wid"</span><span class="token keyword">:</span> 2,
<span class="token string">"id"</span><span class="token keyword">:</span> <span class="token string">"guide1"</span>,
<span class="token string">"account"</span><span class="token keyword">:</span> -1,
<span class="token string">"unconfirmed"</span><span class="token keyword">:</span> 0,
<span class="token string">"confirmed"</span><span class="token keyword">:</span> 0
<span class="token punctuation">}</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><p>Without it, we get a 403 Forbidden error.</p>
<pre class="snippet line-numbers language-bash"><code class="line-numbers language-bash">~$ bcoin wallet balance --id guide1Error: Status code: 403.
at HTTPClient._request <span class="token punctuation">(</span>/opt/bitnami/nodejs/lib/node_modules/bcoin/lib/http/client.js:229:11<span class="token punctuation">)</span>
at process._tickCallback <span class="token punctuation">(</span>internal/process/next_tick.js:109:7<span class="token punctuation">)</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><p>However, we can change our token for this wallet as often as we&#39;d like. In a production-like setting, you&#39;d probably want to encrypt the wallet with a passphrase which would also be required for the <code>retoken</code> call below. </p>
<pre class="snippet line-numbers language-bash"><code class="line-numbers language-bash">~$ bcoin wallet retoken --id guide1 --token c88bc2fda2f265bc00c8fd28771c62695dbbddfd05ef2510f9e0afbec14818ba
26ea429fe1c0da8505c9b0e61a46343d802779d73393ee72130df0fb1a9eaa7e</code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><h4 id="creating-an-account">Creating an Account</h4><p>With our new token, let&#39;s create an account for John Doe&#39;s sister, Jane.</p>
<pre class="snippet line-numbers language-bash"><code class="line-numbers language-bash">~$ bcoin wallet --id guide1 account create jane_doe --token 26ea429fe1c0da8505c9b0e61a46343d802779d73393ee72130df0fb1a9eaa7e
<span class="token punctuation">{</span>
<span class="token string">"wid"</span><span class="token keyword">:</span> 2,
<span class="token string">"id"</span><span class="token keyword">:</span> <span class="token string">"guide1"</span>,
<span class="token string">"name"</span><span class="token keyword">:</span> <span class="token string">"jane_doe"</span>,
<span class="token string">"initialized"</span><span class="token keyword">:</span> true,
<span class="token string">"witness"</span><span class="token keyword">:</span> false,
<span class="token string">"watchOnly"</span><span class="token keyword">:</span> false,
<span class="token string">"type"</span><span class="token keyword">:</span> <span class="token string">"pubkeyhash"</span>,
<span class="token string">"m"</span><span class="token keyword">:</span> 1,
<span class="token string">"n"</span><span class="token keyword">:</span> 1,
<span class="token string">"accountIndex"</span><span class="token keyword">:</span> 1,
<span class="token string">"receiveDepth"</span><span class="token keyword">:</span> 1,
<span class="token string">"changeDepth"</span><span class="token keyword">:</span> 1,
<span class="token string">"nestedDepth"</span><span class="token keyword">:</span> 0,
<span class="token string">"lookahead"</span><span class="token keyword">:</span> 10,
<span class="token string">"receiveAddress"</span><span class="token keyword">:</span> <span class="token string">"n4RwFEkSV7MSxBqqvNziakuGgeS8XFusKq"</span>,
<span class="token string">"nestedAddress"</span><span class="token keyword">:</span> null,
<span class="token string">"changeAddress"</span><span class="token keyword">:</span> <span class="token string">"mfaHH8ESM8pzoR1wLSSRQS89kpaBi9dBVt"</span>,
<span class="token string">"accountKey"</span><span class="token keyword">:</span> <span class="token string">"tpubDCsPHK6xw9CzjZQMnqwoZjLjMHqbkWjNYakAatZ9ktAf6Lou2H7jw2h93x24zT86BadMMmCAsp69yuUjBsGgHkfC41TpgXMPzSZRFxu3Ghi"</span>,
<span class="token string">"keys"</span><span class="token keyword">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><p>We already have the first receiving address for Jane in <code>receiveAddress</code> above, but let&#39;s get one more for good measure.</p>
<pre class="snippet line-numbers language-bash"><code class="line-numbers language-bash">~$ bcoin wallet --id guide1 address --account jane_doe --token 26ea429fe1c0da8505c9b0e61a46343d802779d73393ee72130df0fb1a9eaa7e
<span class="token punctuation">{</span>
<span class="token string">"network"</span><span class="token keyword">:</span> <span class="token string">"testnet"</span>,
<span class="token string">"wid"</span><span class="token keyword">:</span> 2,
<span class="token string">"id"</span><span class="token keyword">:</span> <span class="token string">"guide1"</span>,
<span class="token string">"name"</span><span class="token keyword">:</span> <span class="token string">"jane_doe"</span>,
<span class="token string">"account"</span><span class="token keyword">:</span> 1,
<span class="token string">"branch"</span><span class="token keyword">:</span> 0,
<span class="token string">"index"</span><span class="token keyword">:</span> 1,
<span class="token string">"witness"</span><span class="token keyword">:</span> false,
<span class="token string">"nested"</span><span class="token keyword">:</span> false,
<span class="token string">"publicKey"</span><span class="token keyword">:</span> <span class="token string">"02dda1237f65e26d05451fb96b15e85c3fb5c420ebdfcf31835857c38daa8ef5d6"</span>,
<span class="token string">"script"</span><span class="token keyword">:</span> null,
<span class="token string">"program"</span><span class="token keyword">:</span> null,
<span class="token string">"type"</span><span class="token keyword">:</span> <span class="token string">"pubkeyhash"</span>,
<span class="token string">"address"</span><span class="token keyword">:</span> <span class="token string">"mqDhGEywrWDm5DHw71Qxm5U8Lc6WvhZVeM"</span>
<span class="token punctuation">}</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><h2 id="conclusion">Conclusion</h2><p>After reading this guide, you should have a decent understanding of not only the concepts behind bitcoin wallets, but also of how to go about creating and managing them with bcoin. Now you can integrate bcoin&#39;s wallet functionality directly into your application, or run bcoin as a full node and interact with it for your wallet creation needs. Good luck!</p>
<!-- END OF GUIDE -->
</div>
</div>
</div>
</div>
</article>
<!-- END OF ARTICLE CONTAINER -->
</div>
<!-- END BLOG CONTENT -->
</div><!-- .row -->
</div>
</section>
<!-- END NEW BLOGS -->
</div><!-- .row -->
</div>
</section>
<!-- END BLOGS -->
<!-- PARALLAX DOCS CTA -->
<section class="module bg-white-alfa-30 parallax color-white" data-background="../assets/images/bg-header.jpg">
<div class="container">
<div class="row">
<div class="col-sm-12">
<div class="text-center">
<h2 class="montserrat text-uppercase m-b-30">Ready to start building? Read the docs!</h2>
<a href="http://bcoin.io/docs/index.html" target="_blank" class="btn btn-lg btn-purple">Documentation</a>
</div>
</div>
</div><!-- .row -->
</div>
</section>
<!-- END PARALLAX DOCS CTA -->
<!-- FOOTER -->
<footer id="footer" class="footer-minimal">
<div class="container">
<div class="row">
<div class="col-sm-12">
<ul class="social-icons social-icons-circle text-center m-b-35">
<li><a href="https://twitter.com/bcoin"><i class="fa fa-twitter"></i></a></li>
<li><a href="https://github.com/bcoin-org/bcoin"><i class="fa fa-github"></i></a></li>
<li><a href="../slack-signup.html" target="_blank"><i class="fa fa-slack"></i></a></li>
</ul>
</div>
</div>
<div class="row">
<div class="col-sm-12 text-center m-b-35">
<img class="m-b-35 QR-code" src="../assets/images/donation_QR.png"/>
<p class="m-0"><strong>Bcoin Development Donation Address:</strong><br />3Bi9H1hzCHWJoFEjc4xzVzEMywi35dyvsV</p>
</div>
</div>
<div class="row">
<div class="col-sm-12 text-center">
<p class="m-0">Copyright <a href="#">bcoin.io, Purse</a>, 2017, All Rights Reserved.</p>
</div>
</div>
</div>
</footer>
<!-- END FOOTER -->
</div>
<!-- /WRAPPER -->
<!-- JAVASCRIPT FILES -->
<script src="../assets/js/jquery-2.2.3.min.js"></script>
<script src="http://maps.googleapis.com/maps/api/js?v=3"></script>
<script src="../assets/bootstrap/js/bootstrap.min.js"></script>
<script src="../assets/js/plugins.min.js"></script>
<script src="../assets/js/stickyfill.min.js"></script>
<script src="../assets/js/custom.min.js"></script>
<script src="../assets/js/clipboard.min.js"></script>
<script async defer src="../assets/js/prism.js"></script>
<script>
var copyCode = new Clipboard('.copy-button', {
target: function(trigger) {
return trigger.previousElementSibling;
}
});
copyCode.on('success', function(event) {
event.trigger.classList.add('success');
event.clearSelection();
// event.trigger.textContent = 'Copied!';
window.setTimeout(function() {
event.trigger.classList.remove('success');
}, 2000);
});
</script>
<!-- github button js -->
<script async defer src="https://buttons.github.io/buttons.js"></script>
</body>
</html>

2
guides/working-with-txs.html

@ -267,12 +267,12 @@
<ul class="icons-list">
<!-- GUIDES-LIST -->
<li><a href="working-with-txs.html">Working with transactions</a></li>
<li><a href="wallets.html">Wallets and Accounts and Keys, Oh My!</a></li>
<li><a href="scripting.html">Intro to Scripting</a></li>
<li><a href="op_return.html">Store Data on the Blockchain</a></li>
<li><a href="multisig-tx.html">Creating Multisignature Transactions</a></li>
<li><a href="generate-address.html">Generate an Address</a></li>
<li><a href="crowdfund-tx.html">Create a Crowdfunding Transaction</a></li>
<li><a href="beginners.html">Beginners Guide to Getting Started</a></li>
<!-- /GUIDES-LIST -->
</ul>
</div>

Loading…
Cancel
Save