Application Server
App server
The server project is the aggregation of these three sub projects
The server project provides a away to access information from these three projects via a JSON RPC.
Building the server
Java binary
You can build the server with the sbt native packager. The native packager offers numerous ways to package the project.
In this example we are going to use stage which will produce bash scripts we can easily execute. You can stage the server with the following command.
sbt appServer/universal:stage
This will produce a script to execute bitcoin-s which you can start with
./app/server/target/universal/stage/bin/bitcoin-s-server
Docker
The oracle server also has docker support. You can build a docker image with the following commands
Using an existing docker image
We publish docker images on every PR that is merged to bitcoin-s.
You can find the docker repo for the app server here
Building a docker image
sbt "appServer/docker:stage"
This will build a Dockerfile that is located in app/server/target/docker/stage
You can now build the docker image with
docker build app/server/target/docker/stage/ -t bitcoinscala/bitcoin-s-server:latest
Finally, let's run the image! It's important that you correctly configure port forwarding with the docker container so
you can interact with the running container with bitcoin-s-cli or curl. By default, our oracle
server listens for requests on port 9999. By default, the server listens for websocket connections on port 19999 at /events.
This means we need to forward requests on the host machine to the docker container correctly.
This can be done with the following command
docker run -d -p 9999:9999 -p 19999:19999 -e BITCOIN_S_SERVER_RPC_PASSWORD='topsecret' bitcoinscala/bitcoin-s-server:latest
Now you can send requests with bitcoin-s-cli or curl.
Here is an example with bitcoin-s-cli
./bitcoin-s-cli getblockcount --password topsecret
10000
For more information on build configuration options with sbt please see the sbt native packager docs
Configuration
Java binary configuration
If you would like to pass in a custom datadir for your server, you can do
./app/server/target/universal/stage/bin/bitcoin-s-server --datadir /path/to/datadir/
To use a config file that is not the bitcoin-s.conf file in your datadir, you can do
./app/server/target/universal/stage/bin/bitcoin-s-server --conf /path/to/file.conf
You can also pass in a custom rpcport to bind to
./app/server/target/universal/stage/bin/bitcoin-s-server --rpcport 12345
Or set a custom wsport to bind to
./app/server/target/universal/stage/bin/bitcoin-s-server --wsport 54321
For more information on configuring the server please see our configuration document
For more information on how to use our built in cli to interact with the server please see /docs/1.9.4/applications/cli
Docker configuration
In this example, we are using the latest docker image published to our docker hub
which is referenced by bitcoinscala/bitcoin-s-server:latest
You can use bitcoin-s with docker volumes. You can also pass in a custom configuration at container runtime.
Using a docker volume
docker volume create bitcoin-s
docker run -p 9999:9999 -p 19999:19999 \
--mount source=bitcoin-s,target=/home/bitcoin-s/ bitcoinscala/bitcoin-s-server:latest
Now you can re-use this volume across container runs. It will keep the same oracle database
and seeds directory located at /home/bitcoin-s/.bitcoin-s/seeds in the volume.
Using a custom bitcoin-s configuration with docker
You can also specify a custom bitcoin-s configuration at container runtime. You can mount the configuration file on the docker container and that configuration will be used in the docker container runtime rather than the default one we provide here
You can do this with the following command
docker run -p 9999:9999 -p 19999:19999 \
--mount type=bind,source=/my/new/config/,target=/home/bitcoin-s/.bitcoin-s/ \
bitcoinscala/bitcoin-s-server:latest --conf /home/bitcoin-s/.bitcoin-s/bitcoin-s.conf
Note: If you adjust the bitcoin-s.server.rpcport setting you will need to adjust
the -p 9999:9999 port mapping on the docker container to adjust for this.
Server Endpoints
Common
getversion- The version of our application you are usingzipdatadirlocation- Backs up the datadir in a safe and consistent manner.location- The locations of the backup zip
Blockchain
getblockcount- Get the current block heightgetfiltercount- Get the number of filtersgetfilterheadercount- Get the number of filter headersgetbestblockhash- Get the best block hashgetblockheader- Returns information about block headerhash- The block hash
decoderawtransactiontx-Decode the given raw hex transactiontx- Transaction encoded in hex to decode
getmediantimepast- Returns the median time past
Wallet
rescan[options]- Rescan for wallet UTXOs--force- Clears existing wallet records. Warning! Use with caution!--batch-size <value>- Number of filters that can be matched in one batch--start <value>- Start height--end <value>- End height--ignorecreationtime- Ignores the wallet creation date and will instead do a full rescan
isempty- Checks if the wallet contains any datawalletinfo- Returns data about the current wallet being usedgetbalance[options]- Get the wallet balance--sats- Display balance in satoshis
getconfirmedbalance[options]- Get the wallet balance of confirmed utxos--sats- Display balance in satoshis
getunconfirmedbalance[options]- Get the wallet balance of unconfirmed utxos--sats- Display balance in satoshis
getbalances[options]- Get the wallet balance by utxo state--sats- Display balance in satoshis
getutxos- Returns list of all wallet utxosgetaddresses- Returns list of all wallet addresses currently being watchedgetspentaddresses- Returns list of all wallet addresses that have received funds and been spentgetfundedaddresses- Returns list of all wallet addresses that are holding fundsgetunusedaddresses- Returns list of all wallet addresses that have not been usedgetaccounts- Returns list of all wallet accountswalletinfo- Returns meta information about the walletcreatenewaccount- Creates a new wallet accountgetaddressinfoaddress- Returns list of all wallet accountsaddress- Address to get information about
getnewaddress- Get a new addresslistreservedutxos- lists all utxos that are reserved in the walletsendtoaddressaddressamount[options]- Send money to the given addressaddress- Address to send toamount- Amount to send in BTC--feerate <value>- Fee rate in sats per virtual byte
sendfromoutpointsoutpointsaddressamount[options]- Send money to the given addressoutpoints- Out Points to send fromaddress- Address to send toamount- Amount to send in BTC--feerate <value>- Fee rate in sats per virtual byte
sweepwalletaddress[options]- Sends the entire wallet balance to the given addressaddress- Address to send to--feerate <value>- Fee rate in sats per virtual byte
sendwithalgoaddressamountalgo[options]- Send money to the given address using a specific coin selection algoaddress- Address to send toamount- Amount to send in BTCalgo- Coin selection algo--feerate <value>- Fee rate in sats per virtual byte
signpsbtpsbt- Signs the PSBT's inputs with keys that are associated with the walletpsbt- PSBT to sign
opreturncommitmessage[options]- Creates OP_RETURN commitment transactionmessage- message to put into OP_RETURN commitment--hashMessage- should the message be hashed before commitment--feerate <value>- Fee rate in sats per virtual byte
bumpfeecpfptxidfeerate- Bump the fee of the given transaction id with a child tx using the given fee ratetxid- Id of transaction to bump feefeerate- Fee rate in sats per virtual byte of the child transaction
bumpfeerbftxidfeerate- Replace given transaction with one with the new fee ratetxid- Id of transaction to bump feefeerate- New fee rate in sats per virtual byte
gettransactiontxid- Get detailed information about in-wallet transactiontxid- The transaction id
lockunspentunlocktransactions- Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.unlock- Whether to unlock (true) or lock (false) the specified transactionstransactions- The transaction outpoints to unlock/lock, empty to apply to all utxos
importseedwalletnamewordspassphrase- Imports a mnemonic seed as a new seed filewalletname- Name to associate with this seedwords- Mnemonic seed words, space separatedpassphrase- Passphrase to encrypt this seed with
importxprvwalletnamexprvpassphrase- Imports a mnemonic seed as a new seed filewalletname- Name to associate with this seedxprv- base58 encoded extended private keypassphrase- Passphrase to encrypt this seed with
exportseedwalletnamepassphrase- Exports the mnemonic seed phrasewalletname- Name to associate with this seedpassphrase- Passphrase to decrypt this seed with
markseedasbackedupwalletnamepassphrase- Marks the seed as backed up. It preventsexportseedfrom returning the mnemonic phrasewalletname- Name to associate with this seedpassphrase- Passphrase to decrypt this seed with
getseedbackuptimewalletnamepassphrase- Returns time when the seed was backed upwalletname- Name to associate with this seedpassphrase- Passphrase to decrypt this seed with
keymanagerpassphrasechangeoldpassphrasenewpassphrase- Changes the wallet passphraseoldpassphrase- The current passphrasenewpassphrase- The new passphrase
keymanagerpassphrasesetpassphrase- Encrypts the wallet with the given passphrasepassphrase- The passphrase to encrypt the wallet with
DLC
createcontractinfoannouncementtotalCollateralpayouts- the announcement to build the contract info for
- the total amount of collateral in the DLC
- The payouts can be in two formats
{ "outcomes" : { "outcome0" : 0, "outcome1": 1, ... }}. The number is the amount of sats paid to YOU for that outcome.[{"outcome":0,"payout":0,"extraPrecision":0,"isEndpoint":true}, {"outcome":1,"payout":1,"extraPrecision":0,"isEndpoint":true}, ...]
decodecontractinfocontractinfo- Decodes a contract info into jsoncontractinfo- Hex encoded contract info
decodeofferoffer- Decodes an offer message into jsonoffer- Hex encoded dlc offer message
decodeacceptaccept- Decodes an accept message into jsonaccept- Hex encoded dlc accept message
decodesignsign- Decodes a sign message into jsonsign- Hex encoded dlc sign message
decodeannouncementannouncement- Decodes an oracle announcement message into jsonannouncement- Hex encoded oracle announcement message
decodeattestmentsattestments- Decodes an oracle attestments message into jsonattestments- Hex encoded oracle attestments message
getdlchostaddress- Returns the public listening address of the DLC NodecreatedlcoffercontractInfocollateral[feerate]refundlocktime[options]- Creates a DLC offer that another party can acceptcontractInfo- Hex encoded contractInfo messagecollateral- Satoshis to fund your side of the DLCfeerate- Fee rate for both funding and closing transactions, in sats/vbytesrefundlocktime- Locktime of the refund transactioncetlocktime <value>- Should not be set unless you know what you are doing. Locktime of the contract execution transactions (defaults to current height)peer- Peer's network address
acceptdlcofferpeer- Accepts a DLC offer given from another partyoffer- Hex encoded dlc offer messagepeer- Peer's network address
acceptdlcofferoffer- Accepts a DLC offer given from another partyoffer- Hex encoded offer message
peer- Peer's network addressacceptdlcofferfromfilepath[destination]- Accepts a DLC offer given from another partypath- Path to dlc offer filedestination- Path to write dlc accept message
contact-addaliasaddressmemoalias- alias for the address like a nameaddress- the tor address for the peermemo- a memo for this contact
contacts-list- lists all contacts in the walletcontact-removeaddressaddress- the tor address for the peer to remove
dlc-contact-adddlcidaddress- Associated a DLC with a peerdlc-contact-removedlcid- Removes a DLC-peer associationaddress- the tor address for the peer to remove
signdlcaccept- Signs a DLCaccept- Hex encoded dlc accept message
signdlcfromfilepath[destination]- Signs a DLCpath- Path to dlc accept filedestination- Path to write dlc sign message
adddlcsigssigs- Adds DLC Signatures into the databasesigs- Hex encoded dlc sign message
adddlcsigsfromfilepath- Adds DLC Signatures into the databasepath- Path to dlc sign file
adddlcsigsandbroadcastsigs- Adds DLC Signatures into the database and broadcasts the funding transactionsigs- Hex encoded dlc sign message
adddlcsigsandbroadcastfromfilepath- Adds DLC Signatures into the database and broadcasts the funding transactionpath- Path to dlc sign file
getdlcfundingtxcontractId- Returns the Funding Tx corresponding to the DLC with the given contractIdcontractId- ContractId of the DLC
broadcastdlcfundingtxcontractId- Broadcasts the funding Tx corresponding to the DLC with the given contractIdcontractId- ContractId of the DLC
executedlccontractIdoraclesigs[options]- Executes the DLC with the given contractIdcontractId- ContractId of the DLCoraclesigs- Array of oracle attestations--noBroadcast- Gives full serialized transaction instead of broadcasting
executedlcrefundcontractId[options]- Executes the Refund transaction for the given DLCcontractId- ContractId of the DLC--noBroadcast- Gives full serialized transaction instead of broadcasting
canceldlcdlcId- Cancels a DLC and unreserves used utxosdlcId- Internal id of the DLC
getdlcs- Returns all dlcs in the walletaddress- optional contact address, if specified the RPC returns only DLCs associated with the given address
getdlcdlcId- Gets a specific dlc in the walletdlcId- Internal id of the DLC
offer-addofferTLVpeerAddressmessage- Puts an incoming offer into the inboxofferTLV- Offer TLVpeer- Peer URI (optional)message- Peer's message or note (optional)
"offer-removehash- Remove an incoming offer from inboxhash- Hash of the offer TLV
offer-sendofferOrTempContractIdpeerAddressmessage- Sends an offer to a peer.offerOrTempContractIdis either an offer TLV or a temporary contract ID.offers-list- List all incoming offers from the inboxgetdlcoffertempContractId- Gets a DLC offer by temporary contract ID.getaddresslabeladdress- gets all labels for an addressgetaddresslabels- returns all addresses with labels in the walletdropaddresslabeladdresslabel- drops the label for a given addressdropaddresslabelsaddress- drops all labels for the given address
Network
getpeers- List the connected peersstop- Request a graceful shutdown of Bitcoin-SsendrawtransactiontxBroadcasts the raw transactiontx- Transaction serialized in hex
PSBT
decodepsbtpsbt- Return a JSON object representing the serialized, base64-encoded partially signed Bitcoin transaction.psbt- PSBT serialized in hex or base64 format
combinepsbtspsbts- Combines all the given PSBTspsbts- PSBTs serialized in hex or base64 format
joinpsbtspsbts- Combines all the given PSBTspsbts- PSBTs serialized in hex or base64 format
finalizepsbtpsbt- Finalizes the given PSBT if it canpsbt- PSBT serialized in hex or base64 format
extractfrompsbtpsbt- Extracts a transaction from the given PSBT if it canpsbt- PSBT serialized in hex or base64 format
converttopsbtunsignedTx- Creates an empty psbt from the given transactionunsignedTx- serialized unsigned transaction in hex
Util
createmultisignrequiredkeys[address_type]- Creates a multi-signature address with n signature of m keys required.nrequired- The number of required signatures out of the n keys.keys- The hex-encoded public keys.address_type-The address type to use. Options are "legacy", "p2sh-segwit", and "bech32"
estimatefee- Returns the recommended fee rate using the fee provider
Sign PSBT with Wallet Example
Bitcoin-S CLI:
bitcoin-s-cli signpsbt cHNidP8BAP0FAQIAAAABWUWxYiPKgdGfXcIxJ6MRDxEpUecw59Gk4NpROI5oukoBAAAAAAAAAAAEPttkvdwAAAAXqRSOVAp6Qe/u2hq74e/ThB8foBKn7IfZYMgGCAAAAADbmaQ2nwAAAEdRIQLpfVqyaL9Jb/IkveatNyVeONE8Q/6TzXAWosxLo9e21SECc5G3XiK7xKLlkBG7prMx7p0fMeQwMH5e9H10mBon39JSrtgtgjjLAQAAUGMhAn2YaZnv25I6d6vbb1kw6Xp5IToDrEzl/0VBIW21gHrTZwXg5jGdALJ1IQKyNpDNiOiN6lWpYethib04+XC9bpFXrdpec+xO3U5IM2is9ckf5AABAD0CAAAAAALuiOL0rRcAABYAFPnpLByQq1Gg3vwiP6qR8FmOOjwxvVllM08DAAALBfXJH+QAsXUAAK4AAAAAAQcBAAAAAAAA
cHNidP8BAP0FAQIAAAABWUWxYiPKgdGfXcIxJ6MRDxEpUecw59Gk4NpROI5oukoBAAAAAAAAAAAEPttkvdwAAAAXqRSOVAp6Qe/u2hq74e/ThB8foBKn7IfZYMgGCAAAAADbmaQ2nwAAAEdRIQLpfVqyaL9Jb/IkveatNyVeONE8Q/6TzXAWosxLo9e21SECc5G3XiK7xKLlkBG7prMx7p0fMeQwMH5e9H10mBon39JSrtgtgjjLAQAAUGMhAn2YaZnv25I6d6vbb1kw6Xp5IToDrEzl/0VBIW21gHrTZwXg5jGdALJ1IQKyNpDNiOiN6lWpYethib04+XC9bpFXrdpec+xO3U5IM2is9ckf5AABAD0CAAAAAALuiOL0rRcAABYAFPnpLByQq1Gg3vwiP6qR8FmOOjwxvVllM08DAAALBfXJH+QAsXUAAK4AAAAAAQcBAAAAAAAA
CURL:
curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "signpsbt", "params": ["cHNidP8BAP0FAQIAAAABWUWxYiPKgdGfXcIxJ6MRDxEpUecw59Gk4NpROI5oukoBAAAAAAAAAAAEPttkvdwAAAAXqRSOVAp6Qe/u2hq74e/ThB8foBKn7IfZYMgGCAAAAADbmaQ2nwAAAEdRIQLpfVqyaL9Jb/IkveatNyVeONE8Q/6TzXAWosxLo9e21SECc5G3XiK7xKLlkBG7prMx7p0fMeQwMH5e9H10mBon39JSrtgtgjjLAQAAUGMhAn2YaZnv25I6d6vbb1kw6Xp5IToDrEzl/0VBIW21gHrTZwXg5jGdALJ1IQKyNpDNiOiN6lWpYethib04+XC9bpFXrdpec+xO3U5IM2is9ckf5AABAD0CAAAAAALuiOL0rRcAABYAFPnpLByQq1Gg3vwiP6qR8FmOOjwxvVllM08DAAALBfXJH+QAsXUAAK4AAAAAAQcBAAAAAAAA"]}' -H "Content-Type: application/json" http://127.0.0.1:9999/
{"result":"cHNidP8BAP0FAQIAAAABWUWxYiPKgdGfXcIxJ6MRDxEpUecw59Gk4NpROI5oukoBAAAAAAAAAAAEPttkvdwAAAAXqRSOVAp6Qe/u2hq74e/ThB8foBKn7IfZYMgGCAAAAADbmaQ2nwAAAEdRIQLpfVqyaL9Jb/IkveatNyVeONE8Q/6TzXAWosxLo9e21SECc5G3XiK7xKLlkBG7prMx7p0fMeQwMH5e9H10mBon39JSrtgtgjjLAQAAUGMhAn2YaZnv25I6d6vbb1kw6Xp5IToDrEzl/0VBIW21gHrTZwXg5jGdALJ1IQKyNpDNiOiN6lWpYethib04+XC9bpFXrdpec+xO3U5IM2is9ckf5AABAD0CAAAAAALuiOL0rRcAABYAFPnpLByQq1Gg3vwiP6qR8FmOOjwxvVllM08DAAALBfXJH+QAsXUAAK4AAAAAAQcBAAAAAAAA","error":null}
Websocket endpoints
Bitcoin-s offers websocket endpoints. By default, the endpoint is ws://localhost:1999/events
You can configure where how the endpoints are configured inside your bitcoin-s.conf
bitcoin-s.server.wsbind=localhost
bitcoin-s.server.wsport=19999
These events are implemented using our internal callback mechanism.
An example event that is defined is our blockprocess event.
Everytime our wallet processes a block, our wallet will notify you via websockets.
Here is an example payload
The current types of events defined are
txprocessed- when the wallet processes a transaction. Every transaction in a block will get relayed currentlyreservedutxos- when the wallet reserves OR unreserves utxosnewaddress- when the wallet generates a new addresstxbroadcast- when the wallet broadcasts a txblockprocessed- when the wallet processes a block
{"type":"blockprocessed","payload":{"raw":"04e0ff2ffce8c3e866e367d305886a3f9d353e557524f61f9cf0c26c46000000000000001206d2e396387bff1c13cbe572d4646abae1ae405f4066ab5e6f5edd6d8f028008a8bb61ffff001af23dd47e","hash":"00000000000000de21f23f6945f028d5ecb47863428f6e9e035ab2fb7a3ef356","confirmations":1,"height":2131641,"version":805298180,"versionHex":"2fffe004","merkleroot":"80028f6ddd5e6f5eab66405f40aee1ba6a64d472e5cb131cff7b3896e3d20612","time":1639688200,"mediantime":1639688200,"nonce":2127838706,"bits":"1a00ffff","difficulty":1.6069135243303364E60,"chainwork":"00000000000000000000000000000000000000000000062438437ddd009e698b","previousblockhash":"00000000000000466cc2f09c1ff62475553e359d3f6a8805d367e366e8c3e8fc","nextblockhash":null}}