Transaction Creation

Ty Everett (ty@projectbabbage.com)

Abstract

We define a concise, transport-independent method by which applications can request the creation of Bitcoin transactions. We specify the use of BRC-8 transaction envelopes, and provide an open-ended and extensible approach to output stipulation by the requesting application. We define the formats for request, response and error messages exchanged between application and wallet software.

Motivation

The motivation behind this Bitcoin wallet transaction creation specification is to provide a standardized method for third-party applications to communicate with Bitcoin wallets. This specification aims to enable applications to request the creation of Bitcoin transactions in a concise and transport-independent way, and to allow wallets to focus on wallet and Bitcoin infrastructure, rather than application-specific functionality — conversely, applications can avoid re-inventing the wheel and the need to become their own Bitcoin wallet and infrastructure providers.

By standardizing the communication protocol between applications and wallets, this specification aims to simplify the development of Bitcoin-related applications, reduce development time and costs, and improve the user experience of Bitcoin-powered applications. Additionally, this specification aims to promote interoperability between different wallets and applications, making it easier for users to switch between wallets and for applications to work with multiple wallets.

Implementing this specification will provide a standard way for web and mobile applications to interface with on-device Bitcoin wallets, improving the security of Bitcoin-related operations and enabling users to better control their Bitcoin transactions. With this specification, applications can avoid the overhead of creating their own Bitcoin wallets, and wallets can focus on their core functionality of managing Bitcoin keys, signing transactions, and interacting with the Bitcoin network.

Overall, this specification aims to provide a simple, open-ended, and extensible approach to Bitcoin transaction creation, with a transport-independent method of communication that enables wallets and applications to work together seamlessly.

Pre-Requisites

In order to implement this specification, Bitcoin wallet software must be able to perform the following functions:

  • Create Bitcoin transactions with any number of outputs that use arbitrary Bitcoin scripts and amounts.

  • Prompt the user for acceptance of transactions requested by third-party applications.

  • Unlock a sufficient number of UTXOs to fund the transaction and capture left-over change outputs.

  • Provide merkle proofs on all inputs to build the BRC-81 formatted response.

Wallets that meet these pre-requisites will be able to fulfill the requirements of this specification.

Scope

The scope of this specification is the definition of standard JSON formats for requesting the creation of a Bitcoin transaction, providing the completed transaction once created, and any errors that prevent the transaction from being created.

The specification is intended to be transport-independent, so considerations related to how these messages are communicated, or matters related to the security or authenticity of such communications, are beyond the scope of this specification.

We have sought to keep the base version of this specification as minimal as possible, while still providing all the information needed by applications. Therefore, we have decided to exclude arbitrary input redemption from this specification, and move it to an extension — namely, BRC-4. We have also chosen to exclude transaction output tracking from the base specification, moving it to BRC-46.

Specification

We specify that there are two relevant parties: an application and a Bitcoin wallet. The application is software that runs on an end-user device (such as a webpage, mobile app, or desktop app) that wants to make use of Bitcoin without building wallet infrastructure themselves. The wallet is software that runs on an end-user device that specializes in the management of a user's Bitcoin-related identity information, private keys, facilitates the transaction creation and signing process, and communicates with the Bitcoin network.

We specify that there exists some abstract communications channel (beyond the scope of this specification) that enables the application and the Bitcoin wallet to communicate in a secure and authenticated manner. This mechanism must facilitate the application making a request to the Bitcoin wallet, and the wallet providing a response back to the application.

We specify that JSON is the format that will be used for the messages exchanged in accordance with this specification. We further specify that there exists some out-of-band means for the application to indicate to the Bitcoin wallet that it intends to invoke and utilize this BRC-1 protocol, as opposed to some other protocol.

For example, if the underlying communications method was HTTP (BRC-5), the application could indicate its intention to use this protocol by sending requests to /v1/createAction instead of /v1/foobar. In effect, this means that there is no need for JSON fields in this specification denoting the message type, since both parties have already established that they are exchanging messages according to the BRC-1 protocol. Specific communication mechanisms that facilitate this are defined by other standards such as BRC-5, BRC-6 and BRC-7.

Transaction Creation Request

We specify that the first message exchanged under this BRC-1 protocol originates from the application, and constitutes a request by the application that a Bitcoin transaction be created by the Bitcoin wallet, as specified by the application.

The Transaction Creation Request comprises a JSON object with the following fields, all of which are required:

FieldDescription

description

A present-tense, human-readable description of the action being performed or represented by this transaction.

outputs

An array of Output Objects.

Output Objects are JSON objects that have the following fields:

FieldDescription

script

A hex-formatted Bitcoin output script, as defined in BRC-14.

satoshis

The number of satoshis that are to be in the output, given as a positive integer.

This provides the wallet with enough information to create the transaction requested by the application. Here is an example of a simple Transaction Creation Request:

{
  "description": "Pay John Galt 3,301 satoshis",
  "outputs": [{
    "script": "76a914b10f7d6c7fda3285e9b98297428ed814374cbd4088ac",
    "satoshis": 3301
  }]
}

In this example, the application is stipulating that one output should be created, containing 3301 satoshis, and that the output should be locked using a pay-to-public-key-hash (BRC-16) locking script.

The application also provides a simple description that can be used by the wallet when prompting the user for authorization to proceed with the creation of the transaction, or later when showing the transaction in a list.

Transaction Creation Response

If the transaction is successfully created by the Bitcoin wallet according to the instructions provided by the application, we specify that the Bitcoin wallet assembles a BRC-8 Transaction Envelope and returns it to the user. We specify that, in addition to the required BRC-8 envelope fields, a txid field is also included in the returned Envelope Object for the convenience of the application.

For added clarity, we denote a table comprising the standard BRC-8 Transaction Envelope fields with our additional txid field:

FieldDescription

rawTx

The BRC-12 transaction in hex format

inputs

An object whose keys are the TXIDs of all inputs to this transaction and whose values are BRC-8 envelopes for the respective transactions (the child envelopes are not required to contain the extra txid field), (required unless proof is provided)

mapiResponses

An array of objects where each object comprises a positive endorsement of the transaction from a Bitcoin miner (required unless proof is provided)

proof

A BRC-10 merkle proof for the transaction in JSON format (required unless inputs and mapiResponses are given)

txid

The Bitcoin TXID associated with this transaction

Here is an example of a simple Transaction Creation Response:

{
  "rawTx": "01000000017c36b9ed1c6284079fa9b2111d47e934460d2af631ceda3ffc1bf0587129d1b7020000006b483045022100c655d8c0bfc895c861dda240010c23d5267fd4414894794d3f3591fb7d59fe090220627246ff28e1776c34fd09fbbcfc5bb2efa8090350b35192f1638dd9143ea2a8412102c6848b9988deb921e645fbac47f196e7bec44a6f8612874632240aadc4a35b5bffffffff03e50c0000000000001976a914b10f7d6c7fda3285e9b98297428ed814374cbd4088acc8000000000000001976a914652138f4b89dd615def2c3aa7e13bc1900b5cff588ac1f450000000000001976a91428e5b6157e4a72d8bc8d2374f7acec1388be52f988ac00000000",
  "inputs": {
    "b7d1297158f01bfc3fdace31f62a0d4634e9471d11b2a99f0784621cedb9367c": {
      "proof": {
        "index": 16349,
        "txOrId": "b7d1297158f01bfc3fdace31f62a0d4634e9471d11b2a99f0784621cedb9367c",
        "targetType": "header",
        "target": "00c0322ac50d5e7f9cb2f9be53a34f78fe1cdd7029a03eeeb50b780000000000000000002cb6066c3101dddf29a7853051487bada9adeb9807d2ab4360ca47d3c30581138d9a1264eb370d1802029180",
        "nodes": [
          "95733f96fa3a1f0ba779627d7dc62891f6eee8a13eb0e5a5610bf0d5d1686401",
          "ac95afde3cb7d2f639e3a36d07db7b0becc4bbcb393dce51e322adc38f78c5a1",
          "4054dae1209fa48797dc459239eb396b6220618c9a8bd93776f7485f14759fb7",
          "8f6327bf637241b3e5b029475f3bf5856b263248fa18272e04ec8dae35131351",
          "4da5d84ccde803ba4515ee1f8912b49c738bbc145850d1f88885474ff57d1f58",
          "ec1e6e5c0f50ac2eb8e493c1c372aedde359cbf706643a6bdfaa3aebf4996f01",
          "cedf75aa7314f898121bccdf27eb8b6769262324460a98bf84cdaa6a0379895e",
          "246a798ac6e7e3a5893cb24aa26ca92f71309f41200e1fafbad33a138ea709d6",
          "a5df0501e2c74677b0201fa2b2a6b9cf4156f8266bbc73767e4a784d0793d557",
          "774bdbf5a5992baf1aea1cb80afb68ed93d03aba37b16b57c9fb4cf596e522e6",
          "b621a1f5f431843ed450a09c9a09f245290db204ffe2068732b7c278f4fa2605",
          "93dd7a58841fa52e8d1ac8e5d4bef852450a716c79a603dd4b85772abd0cc0db",
          "57860c6a1f278979fc4540c98f43dc41d64c6f52dffa6aaaf7b07d206e8ca5b5",
          "5de27bdb3b0123c2149d3cc8a54cab926ddc50f93639b02be0885ff9c4365fc8",
          "5cdd1beb2c59b2dbf9be5790633c0a58ea274e2669f52226343648c1a1ca31cc",
          "560490ecae5c1d075dbaf6ee26b61bd758bfbadd09a6cee475156f1b0a3fc9c7"
        ]
      },
      "rawTx": "01000000011a348074d8fe477dec48fe3c07b493371c9fa8b5a49d5d0424916a65b65e77be020000006b4830450221009acfd97f48c819d0fe0ae59df2110eb8a7f6defe948bcf556562b4d1f5e7129602202586aa5f2cb767eba3978aa3185f09e8ec745fcb1111296ca42fb384f7355b6c412102466ef576171e0e0684081f2a99b5e6b5786dac80b5d6d64fec3b033628763a4fffffffff0394070000000000001976a914d75cf5dc3ce0767b005b71b2a8705809ba4b815088acc8000000000000001976a914931c8716ddfb85f4ea4bbdad395d27bd6323b57688acea520000000000001976a914dbdbf9c3216c9cf526e18bc9f976018881972fff88ac00000000"
    }
  },
  "mapiResponses": [
    {
      "payload": "{\"apiVersion\":\"\",\"timestamp\":\"2023-03-17T05:09:51.554Z\",\"txid\":\"737a1e90af9745da3f22ef74bc71a089c5e2a76e9662a0c9fa5b7cf94fe32e75\",\"returnResult\":\"success\",\"resultDescription\":\"\",\"minerId\":\"03ad780153c47df915b3d2e23af727c68facaca4facd5f155bf5018b979b9aeb83\",\"currentHighestBlockHash\":\"00000000000000000138b377cab18dc72cc7ac38d6631949c9694071855bcce8\",\"currentHighestBlockHeight\":783508,\"txSecondMempoolExpiry\":0}",
      "publicKey": "03ad780153c47df915b3d2e23af727c68facaca4facd5f155bf5018b979b9aeb83",
      "signature": "304402201529238a9cf64b02dad0d4573ef5a0780bddb2fe6d6afdca1473e340a6e1512202204845c0721bdb8b6b8ec0e255f120e5749c373a8e2fe13fed208c3154197846c0"
    },
    {
      "payload": "{\"apiVersion\":\"1.5.0\",\"timestamp\":\"2023-03-17T05:09:51.7263993Z\",\"txid\":\"737a1e90af9745da3f22ef74bc71a089c5e2a76e9662a0c9fa5b7cf94fe32e75\",\"returnResult\":\"success\",\"resultDescription\":\"\",\"minerId\":\"030d1fe5c1b560efe196ba40540ce9017c20daa9504c4c4cec6184fc702d9f274e\",\"currentHighestBlockHash\":\"00000000000000000138b377cab18dc72cc7ac38d6631949c9694071855bcce8\",\"currentHighestBlockHeight\":783508,\"txSecondMempoolExpiry\":0,\"warnings\":[],\"failureRetryable\":false}",
      "publicKey": "030d1fe5c1b560efe196ba40540ce9017c20daa9504c4c4cec6184fc702d9f274e",
      "signature": "3044022013546dbe4b9f402ae684f3ac51bbdef5ebe5a1b1abd646b04b9a35e94515a29e022041f4b047caa6d49d1fc4ff202646939d91abd661776d75d9e5dee6b2b355645a"
    }
  ],
  "txid": "737a1e90af9745da3f22ef74bc71a089c5e2a76e9662a0c9fa5b7cf94fe32e75"
}

Transaction Creation Error

If the Bitcoin wallet is unable to fulfill the Transaction Creation Request for any reason, we specify that it should respond with a JSON-formatted Transaction Creation Error. The fields for the object are specified as follows:

FieldDescription

status

This should always be a string comprising "error".

code

A machine-readable error code. Extensions to this standard can define specific error codes and standardize additional fields. Codes are strings, for example "ERR_NOT_SUFFICIENT_FUNDS".

description

All errors must have a human-readable description field that describes the error. This allows the application to represent the error for the user.

One example of a Transaction Creation Error is given below:

{
  "status": "error",
  "code": "ERR_PERMISSION_DENIED",
  "description": "You have denied permission for creating this Bitcoin transaction."
}

Implementations

This specification has been implemented into various wallets and applications:

  • The Babbage MetaNet Client implements BRC-5, the local HTTP substrate including this specification. Transaction Creation Request objcts are sent to the client, which then returns either a Transaction Creation Response or a Transaction Creation Error, after prompting the user.

  • Babbage has implemented a ToDo List application that creates Transaction Creation Request objects which are then received and processed by any wallet software running on a user device that implements this specification.

  • The Ninja Bitcoin wallet, through its getTransactionWithOutputs function, accepts a Transaction Creation Request and returns either a Transaction Creation Response or a Transaction Creation Error.

References

Last updated