bsv-transaction-converter
v1.0.1
Published
Bitcoin SV transaction format converter (RAW, EF, BEEF)
Maintainers
Readme
BSV Transaction Converter
TypeScript library for converting Bitcoin SV transactions between RAW, EF, and BEEF formats.
Although the BSV ecosystem provides ways to work with these formats,
such as the @bsv/sdk,
performing these conversions may require specific knowledge of the
protocol, the SDK APIs, and the external sources needed to obtain the
data that make up each format.
The BSV Transaction Converter abstracts these integrations and provides a simple interface for performing the conversions. Simply provide the transaction and, when necessary, the credentials for the integrated APIs so that the additional data can be retrieved automatically. You can also provide this data directly and run the entire process offline.
Maintaining and operating a full node can be costly, so applications may rely on transaction processors to submit their transactions to the network. During processing, retrieving the data required to validate each transaction separately from the blockchain requires additional requests, increasing latency and bandwidth consumption. Extended formats such as EF and BEEF help reduce this dependency by carrying that data along with the transaction itself.
What it is
BSV transactions can be transmitted in different formats depending on the context in which they are used. This library provides three converters:
| Converter | Input | Output |
|---|---|---|
| EFPackager | RAW | EF |
| BEEFPackager | RAW | BEEF |
| BEEFToEFConverter | BEEF | EF |
Transaction processors allow applications to submit transactions to the network without having to operate a full node directly. During processing, however, information missing from the RAW serialization may need to be retrieved from the blockchain, resulting in additional requests. Extended formats such as EF and BEEF reduce this need by carrying that information along with the transaction.
In the BSV ecosystem, ARC is a transaction processor that can work with these representations. The BSV Transaction Converter does not broadcast transactions: its role is to generate the output representation, which can then be used by the consuming application, including for submission to a transaction processor of its choice.
The formats used by the library are defined by the following specifications:
RAW: standard serialization of a Bitcoin SV transaction.
EF (Extended Format, BRC-30): inserts the referenced output data (value + locking script) after the
sequencefield of each input. This allows the transaction to be validated without having to retrieve its parent transactions.BEEF (Background Evaluation Extended Format, BRC-62): in the representation supported by this library, packages the target transaction together with its already-mined parent transactions and their respective Merkle proofs (BUMPs), enabling SPV verification without access to a full node.
Terminology
Throughout the documentation, the notation Source --> Destination
is used to represent a conversion between formats.
The following terms are used throughout this documentation:
Target transaction: transaction provided to the operation whose representation will be converted to another format.
Parent transaction: transaction that created at least one of the outputs consumed by the inputs of the target transaction. The same parent transaction may be referenced by more than one input.
Conversion: transformation of a transaction from one representation format to another, potentially preserving or appending information during the process.
Packaging: a particular case of conversion in which information is appended to the RAW representation to produce an extended format.
BUMP (BRC-74): Merkle proof structure used to demonstrate the inclusion of one or more transactions in a block.
Therefore, according to this terminology, RAW --> EF and RAW -->
BEEF are conversions and, more specifically, packaging operations.
BEEF --> EF is a conversion, but not a packaging operation.
Quick start
Installation
npm install bsv-transaction-converter
The examples below use offline mode and directly provide all the data required for each conversion. This means they can be run without credentials, external requests, or additional configuration. Simply copy and run the code to obtain the indicated output.
RAW --> EF
import { EFPackager } from 'bsv-transaction-converter';
const packager = new EFPackager();
const childRawTx =
'0100000001ea3f3d4bb804e791bbc8ae3925d1294987eeddd035383b338295499cd3a92d3e000000000201daffffffff01bc020000000000000301da8700000000';
const ef = await packager.execute(childRawTx, {
'3e2da9d39c499582333b3835d0ddee874929d12539aec8bb91e704b84b3d3fea':
'01000000012df46c0ff2be99e27df6ea03d5e0bf8e9dbca9b144e89ea38c2563dcb3359380000000000201daffffffff0120030000000000000301da8700000000',
});
console.log(ef);
//'010000000000000000ef01ea3f3d4bb804e791bbc8ae3925d1294987eeddd035383b338295499cd3a92d3e000000000201daffffffff20030000000000000301da8701bc020000000000000301da8700000000'
RAW --> BEEF
import { BEEFPackager, type BEEFParentMap } from
'bsv-transaction-converter';
const packager = new BEEFPackager();
const childRawTx =
'0100000001419cb100c099ca7b78ede618af92bac46187bc55934323d4b43fd3ce2bbd29b7000000000201daffffffff0158020000000000000301da8700000000';
const parents: BEEFParentMap = {
'b729bd2bced33fb4d423439355bc8761c4ba92af18e6ed787bca99c000b19c41': {
rawTx:
'0100000001ea3f3d4bb804e791bbc8ae3925d1294987eeddd035383b338295499cd3a92d3e000000000201daffffffff01bc020000000000000301da8700000000',
merklePath:
'fe9e7b1a00040209004ae387e1b343b26bac7ae20ba10c0ccfc0b93ce6c7157bd78f48ef0ce9c6ed330802419cb100c099ca7b78ede618af92bac46187bc55934323d4b43fd3ce2bbd29b701050070c43912464c02085348b4b1452e733ab465fa49b3dee8ca8074ba42950b2896010300c9d3ecb30f40903c4c99dd5b6525596eac01eea943a30f6d2c1cc0c320aab78a010000e08c880f48f208d00371031fefea30693fb140d21ef40d03d556a83f1fd5f9cb',
},
};
const beef = await packager.execute(childRawTx, { parents });
console.log(beef);
//'0100beef01fe9e7b1a00040209004ae387e1b343b26bac7ae20ba10c0ccfc0b93ce6c7157bd78f48ef0ce9c6ed330802419cb100c099ca7b78ede618af92bac46187bc55934323d4b43fd3ce2bbd29b701050070c43912464c02085348b4b1452e733ab465fa49b3dee8ca8074ba42950b2896010300c9d3ecb30f40903c4c99dd5b6525596eac01eea943a30f6d2c1cc0c320aab78a010000e08c880f48f208d00371031fefea30693fb140d21ef40d03d556a83f1fd5f9cb020100000001ea3f3d4bb804e791bbc8ae3925d1294987eeddd035383b338295499cd3a92d3e000000000201daffffffff01bc020000000000000301da870000000001000100000001419cb100c099ca7b78ede618af92bac46187bc55934323d4b43fd3ce2bbd29b7000000000201daffffffff0158020000000000000301da870000000000'
The examples above use offline mode so they can be reproduced without credentials or external dependencies. The library can also automatically retrieve the required data through online mode. See Operating modes to learn about both usage modes.
Operating modes
EFPackager and BEEFPackager can operate in offline
and online modes. The selected mode determines how the
additional data required for packaging is obtained.
In offline mode, this data is provided directly by the
application when calling execute(). This mode is suitable when the
parent transactions and, when required, their BUMPs are already
available in the application's flow.
In online mode, only the target transaction needs to be provided. The library automatically retrieves the additional required data through the integrated external services, reducing the need to implement specific requests and integrations for packaging.
BEEFToEFConverter is an exception: it always operates offline
because all data required for the conversion is already contained in the
BEEF itself.
| Operation | Offline | Online | |---|:---:|:---:| | RAW --> EF | ✓ | ✓ | | RAW --> BEEF | ✓ | ✓ | | BEEF --> EF | ✓ | --- |
RAW --> EF
Offline
In offline mode, parent transactions are provided directly in a map where each key corresponds to a parent transaction TXID and the value contains its RAW representation.
import { EFPackager } from 'bsv-transaction-converter';
const packager = new EFPackager();
const childRawTx = '<child-raw-transaction>';
const parentRaws = {
'<parent-txid>': '<parent-raw-transaction>',
};
const ef = await packager.execute(childRawTx, parentRaws);
Online
In online mode, only the target transaction is provided. The
EFPackager automatically queries WhatsOnChain to
retrieve the required parent transactions.
The configured network determines where external data is retrieved from.
The library uses testnet by default; to operate on mainnet, use
network: 'mainnet'. The wocApiKey field is also optional and can
be provided when a WhatsOnChain API key is available.
import { EFPackager } from 'bsv-transaction-converter';
const packager = new EFPackager({
network: 'testnet', // optional, defaults to 'testnet'
wocApiKey: '<woc-api-key>', // optional
});
const childRawTx = '<child-raw-transaction>';
const ef = await packager.execute(childRawTx);RAW --> BEEF
Offline
In offline mode, each parent transaction must be provided together with
its corresponding BUMP through a BEEFParentMap.
import { BEEFPackager, type BEEFParentMap } from
'bsv-transaction-converter';
const packager = new BEEFPackager();
const childRawTx = '<child-raw-transaction>';
const parents: BEEFParentMap = {
'<parent-txid>': {
rawTx: '<parent-raw-transaction>',
merklePath: '<parent-bump>',
},
};
const beef = await packager.execute(childRawTx, { parents });Online
In online mode, only the target transaction is provided. The
BEEFPackager automatically queries WhatsOnChain to
retrieve the parent transactions and the configured ARC
instance to retrieve their BUMPs.
The library uses testnet by default. To operate on mainnet, use
network: 'mainnet'. In online mode, arcApiKey is required to
query the ARC instance. wocApiKey is optional and can be provided
when a WhatsOnChain API key is available.
import { BEEFPackager } from 'bsv-transaction-converter';
const packager = new BEEFPackager({
network: 'testnet', // optional, defaults to 'testnet'
arcApiKey: '<arc-api-key>', // required
wocApiKey: '<woc-api-key>', // optional
});
const childRawTx = '<child-raw-transaction>';
const beef = await packager.execute(childRawTx);BEEF --> EF
BEEFToEFConverter operates exclusively offline. Because the BEEF
already contains the data required for the conversion, no configuration
or external requests are required.
import { BEEFToEFConverter } from 'bsv-transaction-converter';
const converter = new BEEFToEFConverter();
const beefHex =
'0100beef01fe636d0c0007021400fe507c0c7aa754cef1f7889d5fd395cf1f785dd7de98eed895dbedfe4e5bc70d1502ac4e164f5bc16746bb0868404292ac8318bbac3800e4aad13a014da427adce3e010b00bc4ff395efd11719b277694cface5aa50d085a0bb81f613f70313acd28cf4557010400574b2d9142b8d28b61d88e3b2c3f44d858411356b49a28a4643b6d1a6a092a5201030051a05fc84d531b5d250c23f4f886f6812f9fe3f402d61607f977b4ecd2701c19010000fd781529d58fc2523cf396a7f25440b409857e7e221766c57214b1d38c7b481f01010062f542f45ea3660f86c013ced80534cb5fd4c19d66c56e7e8c5d4bf2d40acc5e010100b121e91836fd7cd5102b654e9f72f3cf6fdbfd0b161c53a9c54b12c841126331020100000001cd4e4cac3c7b56920d1e7655e7e260d31f29d9a388d04910f1bbd72304a79029010000006b483045022100e75279a205a547c445719420aa3138bf14743e3f42618e5f86a19bde14bb95f7022064777d34776b05d816daf1699493fcdf2ef5a5ab1ad710d9c97bfb5b8f7cef3641210263e2dee22b1ddc5e11f6fab8bcd2378bdd19580d640501ea956ec0e786f93e76ffffffff013e660000000000001976a9146bfd5c7fbe21529d45803dbcf0c87dd3c71efbc288ac0000000001000100000001ac4e164f5bc16746bb0868404292ac8318bbac3800e4aad13a014da427adce3e000000006a47304402203a61a2e931612b4bda08d541cfb980885173b8dcf64a3471238ae7abcd368d6402204cbf24f04b9aa2256d8901f0ed97866603d2be8324c2bfb7a37bf8fc90edd5b441210263e2dee22b1ddc5e11f6fab8bcd2378bdd19580d640501ea956ec0e786f93e76ffffffff013c660000000000001976a9146bfd5c7fbe21529d45803dbcf0c87dd3c71efbc288ac0000000000';
const ef = await converter.execute(beefHex);
console.log(ef);
//'010000000000000000ef01ac4e164f5bc16746bb0868404292ac8318bbac3800e4aad13a014da427adce3e000000006a47304402203a61a2e931612b4bda08d541cfb980885173b8dcf64a3471238ae7abcd368d6402204cbf24f04b9aa2256d8901f0ed97866603d2be8324c2bfb7a37bf8fc90edd5b441210263e2dee22b1ddc5e11f6fab8bcd2378bdd19580d640501ea956ec0e786f93e76ffffffff3e660000000000001976a9146bfd5c7fbe21529d45803dbcf0c87dd3c71efbc288ac013c660000000000001976a9146bfd5c7fbe21529d45803dbcf0c87dd3c71efbc288ac00000000'
Online-mode limitations of BEEFPackager
The BEEFPackager is responsible for RAW --> BEEF packaging. In
online mode, this operation depends on retrieving the parent
transactions' BUMPs through the configured ARC instance.
BUMP availability
An ARC instance obtains the data required to provide a transaction's
BUMP when that instance itself broadcasts the transaction. Consequently,
the BEEFPackager can automatically retrieve a parent transaction's
BUMP only when that data is available in the configured ARC instance.
If a parent transaction was submitted to the network through another ARC
instance or another broadcast interface, its BUMP will not necessarily
be available from the instance queried by the BEEFPackager.
Data completeness
To perform this packaging operation, the BEEFPackager must obtain
the BUMPs for all parent transactions required to represent the target
transaction.
Therefore, having only part of this data available is not sufficient. If the BUMP for any required parent transaction cannot be obtained from the configured ARC instance, the packaging operation cannot be completed.
Data persistence
Even when a BUMP is available from the ARC instance, its future availability depends on the provider's retention policy. An external instance may remove this data later, causing a previously accessible BUMP to become unavailable for new operations.
Alternatives
Some alternatives for reducing dependency on the data availability of an external provider include:
operating your own ARC instance, providing greater control over processing and data availability;
using, when available, an external service dedicated to retrieving or generating BUMPs.
By default, online mode uses an ARC instance operated by TAAL and requires a valid API key. The consuming application can configure the ARC instance to use. See the API section for more details.
Input validation and error handling
Input validation
The library does not perform an additional validation step on the hexadecimal value provided as the input transaction. It assumes that the received value represents a valid serialized transaction.
This decision is intentional. In a normal usage flow, the input transaction is produced by a wallet, SDK, or another tool responsible for constructing and serializing it. Therefore, the library treats the structural validity of this input as the responsibility of the consuming application and keeps its scope limited to conversion and packaging between the supported formats.
Invalid inputs may still result in errors while parsing or processing the transaction, but the library does not perform a dedicated pre-validation step.
Error handling
The library handles errors in situations where a conversion cannot be completed due to missing data, inconsistencies found during processing, or failures in dependencies required for the operation. In these cases, execution is stopped and an error is thrown with information about the cause of the failure.
In online mode, errors related to external requests are contextualized before being propagated. When applicable, the message includes information such as the TXID associated with the operation and the HTTP status returned by the external service, making it easier to identify the transaction or dependency responsible for the failure.
API
EFPackager
Constructor
new EFPackager(config?: EFPackagerConfig)| Option | Type | Default | Description |
|---|---|---|---|
| network | 'mainnet' \| 'testnet' | 'testnet' | Target network |
| wocApiKey | string | — | WhatsOnChain API key used in online mode |
execute()
packager.execute(
childRawTx: string,
parentRaws?: { [txid: string]: string }
): Promise<string>
childRawTx must contain the target transaction in RAW format to be packaged as EF.
When parentRaws is omitted, the EFPackager operates in online
mode and automatically retrieves the required parent transactions.
When parentRaws is provided, the EFPackager operates in offline
mode. The map must associate each parent transaction TXID with that
transaction's RAW hexadecimal representation:
parent transaction TXID -> RAW transaction hexAll TXIDs referenced by the inputs of childRawTx must be present in
the map. If any of them is missing, an error will be thrown.
BEEFPackager
Constructor
new BEEFPackager(config?: BEEFPackagerConfig)| Option | Type | Default | Description |
|---|---|---|---|
| network | 'mainnet' \| 'testnet' | 'testnet' | Target network |
| arcUrl | string | Default TAAL ARC endpoint | Base URL of the ARC instance |
| arcApiKey | string | — | ARC instance API key, required in online mode |
| wocApiKey | string | — | WhatsOnChain API key used in online mode |
execute()
packager.execute(
childRawTx: string,
options?: { parents?: BEEFParentMap }
): Promise<string>
childRawTx must contain the target transaction in RAW format to be
packaged as BEEF.
When options.parents is omitted, the BEEFPackager operates in
online mode, automatically retrieving the required parent transactions
and BUMPs. In this mode, a valid arcApiKey is required.
When options.parents is provided, the BEEFPackager operates in
offline mode. The BEEFParentMap must associate each parent
transaction TXID with that transaction's RAW representation and its
corresponding BUMP:
parent transaction TXID -> parent RAW transaction hex + BUMPAll TXIDs referenced by the inputs of childRawTx must be present in
the map, together with their corresponding RAW transactions and BUMPs.
If any of this data is missing, an error will be thrown.
BEEFToEFConverter
Constructor
new BEEFToEFConverter()execute()
converter.execute(beefHex: string): stringbeefHex must contain a transaction in BEEF format encoded as
hexadecimal.
BEEFToEFConverter does not receive configuration and does not
perform external requests. All data required for the conversion is
already contained in the BEEF, so its operation is always offline.
Exported types
import type {
Network,
EFPackagerConfig,
BEEFPackagerConfig,
BEEFParentData,
BEEFParentMap,
} from 'bsv-transaction-converter';| Type | Definição |
|---|---|
| Network | 'mainnet' \| 'testnet' |
| EFPackagerConfig | Constructor options for EFPackager |
| BEEFPackagerConfig | Constructor options for BEEFPackager |
| BEEFParentData | { rawTx: string; merklePath: string } |
| BEEFParentMap | { [txid: string]: BEEFParentData } |
