Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Here is an explanation of the errors you might get returned
OrderNotFound - There is no order in the database with that orderId. Double check that the orderId is correct.
InvalidOrderId - The orderId provided is not a valid UUID. Double check that the orderId is correct.
InvalidRefundAddress - The refund address provided is not a valid Bitcoin address. Double check to make sure the address was input correctly.
InvalidMarket - An invalid market was provided with the request. For valid markets, see Market Documentation.
InvalidOnchainTicker - The asset ticker provided is not valid. For valid tickers, see Asset Abbreviation documentation.
InvalidInvoice - The invoice provided is not a valid Lightning Network invoice. You can decode valid Lightning Network invoices using RADAR ION's invoice decoder.
InvoiceExpiresTooSoon - The invoice provided expires too soon.
InvoiceAmountBelowMinimum - Invoice is below the minimum amount for selected market.
InvoiceAmountAboveMaximum - Invoice is above the maximum amount for selected market.
InvoicePaymentNotRoutable - There is no route between the liquidity provider and the invoice recipient. Usually a result of the invoice recipient not having a well connected Lightning node. Can be resolved by having the invoice recipient open a channel to another well connected node like RADAR ION's.
TooManySwapsInFlight - There are too many swaps happening at once. Can be resolved by waiting and sending another request.
InvalidSignedTxHex - The signed transaction hex is invalid. Double check the transaction hex or generate a different one.
InvalidNetworkOrSubnet - The provided network or subnet is not valid. See
InactiveNetworkOrSubnet - The provided network or subnet is not active.
InternalServerError - There was an error during one of the requests. Retry the request.
NoQuoteProvidersAvailable - There are no quote providers available for the particular market. This is very unusual. Contact support or wait and retry request.
Market
Invoice Minimum
Invoice Maximum
Min Invoice Expiration
BTC_LBTC
30000 satoshis
1000000 satoshis
2400 sec
ETH_LBTC
1 satoshi
1000000 satoshis
900 sec
There is a lot of language native to submarine swaps
Submarine Swap - an atomic on-chain to off-chain swaps of cryptocurrencies. REDSHIFT currently supports swaps of on-chain assets like Bitcoin, Ether, or DAI for Lightning Bitcoin. Also referred to as just "swap".
HTLC (Hash Time Lock Contract) - A type of transaction that puts on-chain funds in escrow until someone unlocks them with a preimage or the timelock expires.
Preimage - A string of characters returned when successfully paying a Lightning Network invoice. Think of it as a password. It is used to unlock on-chain funds that are locked up in an HTLC.
Liquidity Provider - The counter-party to a swap that will pay the Lightning Invoice in exchange for an on-chain asset like Bitcoin, Ether, or DAI.
Quote - The price a liquidity provider returns when asked to pay an invoice. Denominated in the requested asset.
WaitingForFundingTx - The HTLC has been created and is waiting for an on-chain funding transaction.
WaitingForFundingTxConfirmation - An on-chain funding transaction has been broadcasted but has not been confirmed.
WaitingForAdditionalFundingTxConfirmation - An on-chain funding transaction has been confirmed but has not met the confirmation threshold required to complete the swap. Wait for more confirmations and the order will move to Funded.
PartiallyFunded - The transaction has been partially funded, meaning a transaction has been sent but the total amount of funds sent has not reached the quote amount. Another transaction must be sent so that the total amount of funding is equal to the amount given in the quote.
Funded - The HTLC has been funded to the correct amount. After quote provider pays the Lightning Invoice, they will receive the preimage to unlock the funds.
WaitingForRefundTx - The swap was not completed successfully and HTLC's timelock has passed. A transaction can be sent to reclaim funds.
AddressBlacklistedWaitingForRefundTx - The transaction cannot be completed because the address is blacklisted. Send a refund transaction to reclaim funds.
WaitingForRefundTxConfirmation - A refund transaction has been broadcast to the network but has not confirmed yet.
Refunded - The refund transaction has been confirmed and the funds have been sent back to the user.
Complete - The swap is complete. The invoice has been paid and the funds from the HTLC have been swept by the liquidity provider.
FundWindowElapsed - The window to fund the HTLC has elapsed. Request a new quote to start the swap process again.
BTC - Bitcoin
ETH - Ether
LBTC - Lightning Bitcoin (Bitcoin locked up in the Lightning Network)
We combine asset abbreviations with an underscore to define markets in REDSHIFT. We currently support the following mainnet market pairs:
BTC_LBTC - Bitcoin to Lightning Bitcoin
ETH_LBTC - Ether to Lightning Bitcoin
When working in a testing environment, we append a "T" to the front of UTXO testnet market asset pairs and "K" to Kovan (testnet) Ether market asset pairs. We support the following testnet markets:
TBTC_LTBTC - Testnet Bitcoin to Lightning Testnet Bitcoin
KETH_LTBTC - Testnet Ether to Lightning Testnet Bitcoin
Like testnet, we append an "S" to the beginning of market assets on simnet. We support the following simnet markets:
SBTC_LSBTC - Simnet Bitcoin to Lightning Simnet Bitcoin
SETH_LSBTC - Simnet Ether to Lightning Simnet Bitcoin
Endpoints to retrieve market requirements.
GET
https://api.redshift.radar.tech/api/markets
This endpoint allows you view available markets
GET
https://api.redshift.radar.tech/api/markets/requirements
GET
https://api.redshift.radar.tech/api/markets/:market/requirements
Endpoints to interact with and retrieve orders.
GET
https://api.redshift.radar.tech/api/orders
This endpoint allows you to get orders via the lightning invoice and payment asset. Because an actual invoice could potentially exceed the maximum URL length, we use the invoice hash.
Name | Type | Description |
---|
GET
https://api.redshift.radar.tech/api/orders/:id
GET
https://api.redshift.radar.tech/api/orders/:id/state
GET
https://api.redshift.radar.tech/api/orders/:id/fundDetails
GET
https://api.redshift.radar.tech/api/orders/:id/transactions
GET
https://api.redshift.radar.tech/api/orders/:id/refund
Name | Type | Description |
---|
Name | Type | Description |
---|
Name | Type | Description |
---|
Name | Type | Description |
---|
Name | Type | Description |
---|
Name | Type | Description |
---|
market | string | The market to fetch requirements for. |
id | string | The id associated with the order. |
id | string | The id associated with the order. |
id | string | The id associated with the order. |
id | string | The id associated with the order. |
id | string | The id associated with the order. |
invoiceHash | string | The SHA256 hash of the Lightning invoice used to request the quote. |
onchainTicker | string | The ticker code for the payment asset. |
REDSHIFT HTTP & WebSocket Client Library
The REDSHIFT client acts as a wrapper for the HTTP & WebSocket clients.
Mainnet
By default, the REDSHIFT client targets mainnet
If you prefer to be explicit, you can pass RedshiftApiUrl.MAINNET
into the constructor
Testnet
The http
and ws
getters can be used to access the HTTP & WebSocket client methods.
http
- Get Markets Example
Get the active markets
ws
- Connect Example
Establish a connection to the REDSHIFT WebSocket API
The HTTP client can be used to interact with the REDSHIFT HTTP endpoints.
Mainnet
By default, the HTTP client targets mainnet
If you prefer to be explicit, you can pass RedshiftApiUrl.MAINNET
into the constructor
Testnet
Get Markets
Get the active markets
Get Orders
Get all swap orders for a specific invoice
Get Order
Get a single swap order
Get Order State
Get the state of a single order
Get Order Fund Details
Get the fund details for an order
Get Order Transactions
Get the transactions relating to an order
Get Order Refund Details
Get the refund details for a single order
The WebSocket client can be used to interact with the REDSHIFT WebSocket endpoints. Many WebSocket interactions are promisified to provide a better developer experience.
Mainnet
By default, the WebSocket client targets mainnet
If you prefer to be explicit, you can pass RedshiftApiUrl.MAINNET
into the constructor
Testnet
Connect
Establish a connection to the REDSHIFT WebSocket API
Disconnect
Disconnect from the REDSHIFT WebSocket API
Request Quote
Request a quote for the provided invoice and selected on-chain asset
Subscribe to Order State
Subscribe to order state updates for the provided order id
On Order State Changed
Execute the callback function when an order state update is received
Unsubscribe from Order State
Unsubscribe from order state updates for the provided order id
Subscribe to Block Height
Subscribe to block height updates for the provided network and subnet
On Block Height Changed
Execute the callback function when a block height update is received
Unsubscribe from Block Height
Unsubscribe from block height updates for the provided network and subnet
Request Refund Details
Request refund details for a specific swap order
Broadcast Transaction
Broadcast signed transaction hex to your network of choice
Websocket information to communicate with REDSHIFT.
Use this endpoint to request a quote to exchange an on-chain asset for Lightning Bitcoin (LBTC). Available markets are in docs.
Use this endpoint to subscribe to an order's state. If an order's state changes, subscribers will be sent a message with the new state of the order. This may be useful to notify users how their order is progressing.
Use this endpoint to unsubscribe from an order's state. If an order's state changes in the future, the client will not be notified.
Use this endpoint to subscribe to a blockchain's current block height. If the blockchain's current block height changes, subscribers will be sent a message with the new block height. This might be useful to notify users whether they can refund their transaction.
Valid Networks:
bitcoin
ethereum
Valid Subnets:
Bitcoin:
simnet
testnet
mainnet
Ethereum:
ganache_simnet
kovan_testnet
mainnet
Use this endpoint to unsubscribe from a blockchain's current block height. If the blockchain's current block height changes in the future, the client will not be notified.
Valid Networks:
bitcoin
ethereum
Valid Subnets:
Bitcoin:
simnet
testnet
mainnet
Ethereum:
ganache_simnet
kovan_testnet
mainnet
Use this endpoint to request the refund details for a particular order. This information can also be retrieved using the requestRefundDetails HTTP endpoint, but it may make more sense to use an already established WebSocket connection depending on your application.
Use this endpoint broadcasts a signed transaction to the specific network. This can be used to broadcast refund transactions directly from your app without needing to run a node.
Valid onchainTickers are defined in the docs.
Use this endpoint to get the market requirements.
N/A
Tutorials to get a project up and running using the REDSHIFT API
This documentation is your entry point to interacting with submarine swaps programmatically on REDSHIFT
REDSHIFT is a payment network tool that allows Lightning Network payments to be made using on-chain assets like Bitcoin, Ethereum, and ERC-20 tokens.
It utilizes a technology called Submarine Swap in order to make payments in a trustless way - meaning the on-chain asset is controlled by the original owner until the Lightning Payment is sent.
There are a number of use cases for using Submarine Swaps to make Lightning Network payments:
Channel Rebalancing: The payment channels that compose the Lightning Network require maintaining sufficient liquidity in order to send and receive payments. REDSHIFT allows the liquidity within these channels to be adjusted without having to close and re-open channels with peers - avoiding on-chain opening and closing fees and maintaining the channel's successful payment routing history. Essentially, you can "top up" your local channel balance with REDSHIFT.
Merchants: Accept more digital currencies without adding additional infrastructure. If you already accept Lightning Network payments, REDSHIFT enables your customers to pay using other currencies while you still receive payment in LBTC.
Consumers: REDSHIFT allows customers to send payments on the Lightning Network without having to operate their own node or trust custodial wallets with their sats. Simply send on-chain assets from the wallet they already use and the Lighting Network invoice will be paid.
Submarine Swaps utilize a class of payments called Hash Time Locked Contracts (HTLCs).
HTLCs use hashlocks and timelocks to require that the receiver of a payment either acknowledge receiving the payment prior to a deadline by generating cryptographic proof of payment or forfeit the ability to claim the payment, returning it to the payer.
HTLCs are what make REDSHIFT trustless - neither the payer or receiver need to trust that the other party will make their required payment because ownership conditions are baked into the transaction itself.
Alice runs a Lightning Network node that helps route payments through the Lightning Network. She has opened a couple of channels with a handful peers and has been routing payments through them. After a few days, a lot of her balance has accrued on the remote side of her channels.
Instead of closing her lopsided channels and reopening them to regain more local balance, she generates an invoice for her channels with more remote capacity and sends it to REDSHIFT via REDSHIFT's API. REDSHIFT responds with a Bitcoin address and amount to send to the address.
Note: The amount of satoshis Alice will send to the address is typically greater than the amount of satoshis on the invoice. So in Alice's case, she might have to send 100,500 satoshis on-chain in order to fulfill her 100,000 sat invoice. This spread is how liquidity providers (the people paying the Lightning Invoice) make money and cover the cost of the on-chain transaction required to claim their funds after paying the Lightning Invoice that Alice provided.
Alice sends the Bitcoin to the prescribed address and her Lightning Invoice gets paid, pushing the remote balance of the channel back over to her local side, enabling her to send more outgoing payments through the channel without having to close and reopen it.
Alice wants to pay a 100,000 satoshi Lightning Network invoice with an on-chain asset like Ether. She sends the invoice to REDSHIFT via the REDSHIFT API or a REDSHIFT widget embedded on a webpage. REDSHIFT responds with an unsigned Ethereum transaction, which contains the contract address, input data, and amount of ether to send.
Note: The amount of value of the Ether Alice will send to the address is typically greater than the value of satoshis on the invoice. Let's say that one satoshi is worth $1 and one Ether is worth $1. In this case, Alice might have to send 103,000 Ether on-chain in order to fulfill her 100,000 sat invoice. This spread is how liquidity providers (the people paying the Lightning Invoice) make money and cover the cost of the on-chain transaction required to claim their funds after paying the Lightning Invoice that Alice provided.
Alice sends the prescribed amount of Ether to the address sent back from her REDSHIFT request. These funds are housed in an on-chain escrow protected by HTLCs.
There are now only two ways to claim these funds: either by the liquidity provider using the preimage revealed after paying Alice's Lightning Invoice or by Alice after the timelock has expired.
In most cases, the invoice will be paid and the on-chain asset will be claimed by the liquidity provider. If the invoice is unable to be paid, Alice will be able to re-claim her funds after the timelock expires. This isn't typical but can happen if a route cannot be found.
A library used to construct and interact with HTLCs across multiple networks & network models
Get the HTLC details:
Get the redeem script:
Generate the fund transaction. You can now broadcast it using sendrawtransaction
:
Generate the claim transaction. You can now broadcast it using sendrawtransaction
:
Generate the refund transaction. You can now broadcast it using sendrawtransaction
:
For working examples, view the Absolute or Relative Timelock Bitcoin HTLC tests.
Asset: Ether
Asset: ERC20
Get the deployed HTLC contract instance:
Generate, sign, and broadcast the fund transaction using the passed provider:
Generate and broadcast the claim transaction using the passed provider:
Generate and broadcast the refund transaction using the passed provider:
Want to pass in additional tx params? Pass all desired tx params as the last argument:
Don't want to sign and broadcast the transaction? Set shouldBroadcast
to false to return the unsigned transaction. You can now broadcast it using eth_sendTransaction
:
For working examples, view the Ether or ERC20 Ethereum HTLC tests.
Build, sign, and broadcast a transaction (envelope) to create an escrow account (escrowPubKey):
Build the fundEnvelope
and refundEnvelope
for the user:
Once the user funds, pay the invoice to get the payment secret. Use the payment secret to claim the funds. Once broadcast, the escrow account gets merged into the server account. Swap Complete.
For a working example, view the Stellar HTLC tests.
Subnets should be named SIMNET
, TESTNET
, or MAINNET
if there is only one instance of the subnet type. If there are two or more instances of a single subnet type (multiple testnets, etc.) then the naming convention should be SUBNETNAME_SUBNETTYPE
. e.g. KOVAN_TESTNET
.
Utilities used across REDSHIFT codebases
Validate Network
Determine if the passed network is valid
Validate On-Chain Ticker
Determine if the passed on-chain ticker is valid
Validate Market
Determine if the passed market is valid
Validate UUID
Determine if the passed UUID is valid
Validate Base58Check
Determine if the passed string is valid base58check
Validate Bech32
Determine if the passed string is valid bech32
Validate Base58Check or Bech32
Determine if the passed string is valid base58check or bech32
Validate Hex
Determine if the passed string is a valid hex
Validate Network & Subnet
Determine if the passed network and subnet are valid
In this tutorial, we'll integrate the REDSHIFT Javascript SDK into a Vue frontend that can be used to execute a Kovan Testnet Ether (kETH) <-> Lightning Testnet Bitcoin (ltBTC) submarine swap.
MetaMask is an Ethereum wallet and web3 provider running inside a browser extension. Install MetaMask if not already installed. You can request testnet ether from https://faucet.kovan.network if you do not have any.
In this scenario, a user arrives at the app with a Lightning invoice that they would like REDSHIFT to pay in exchange for ETH. The exchange is atomic and completely trustless. The user will send their ETH to the swap contract, which can only be claimed by REDSHIFT once the invoice has been paid. If REDSHIFT fails to pay the invoice, the user can reclaim their funds from the contract after a couple hours.
We'll begin by taking a look at the Start page.
First, we must fetch two important pieces of information from REDSHIFT: The active markets and market requirements.
The markets are rather self-explanatory. They tell us which markets REDSHIFT is currently servicing.
The market requirements can help inform us if the invoice will be rejected by REDSHIFT without making a round-trip to the server. This call is optional as the server will return the same validation error, but we can offer a better user experience by performing this check on the client-side. The market requirements include the minimum time until invoice expiration, minimum invoice amount, and maximum invoice amount that will be accepted by REDSHIFT.
In our app, we make both calls at the same time as the page is created:
Now that we have the markets and market requirements, we'll collect information from the user required to perform the swap.
At a minimum, we require the invoice that REDSHIFT will pay. If your application only supports one on-chain payment asset, ETH for example, then you will not need to collect the payment asset from the user.
We also support bitcoin payments in our app, so the user is required to select a payment asset.
To provide a better user experience, we'll validate the invoice on the client-side. To do so, we use bolt11-decoder, a lighter version of bolt11, to decode the invoice.
If the invoice does not decode successfully, then it is invalid:
Once the user has input a valid invoice and selected a market, we have enough information to check if the market requirements have been met.
We'll perform this check when the user clicks Pay Invoice
. Alternatively, you could run this validation when the input or select change event fires.
You can see this call in action inside the initiateSwap
method:
If the invoice does not meet the market requirements, the error is set on the input and code execution is stopped.
Once we've validated the information provided by the user, we're ready to request a quote from REDSHIFT.
This is a simple process that involves two steps; establish a WebSocket connection and request the quote:
The quote response will look like this:
We now have everything that we need to request payment from the user. Move to the Payment page for this part of the tutorial.
To provide a good UX, we'll subscribe to order state updates and present them to the user.
You can subscribe to state updates using the following method:
Once subscribed, we must attach an event handler that gets fired when the order state changes. In this sample, we'll feed the state update event to a method called handleStateChange
that will update the state for display, increase the progress bar completion percentage, and populate the payment proof once complete:
As you may have gathered from the above description, not all state updates share the same schema. There are three types of state updates.
Now that our state update listener is hooked up, we're ready to accept payment from the user.
In this example, all MetaMask interactions are handled through the metamask object. We'll skip over many of the actions required to connect and communicate with MetaMask as they are not specific to REDSHIFT.
When the user clicks the Send Payment
button, we need to pass the unsigned funding transaction to MetaMask using the sendTransaction
RPC call. This will pop up the MetaMask window so the user can sign the transaction.
In this example, we use the MetaMask provider to make the RPC call directly:
Note that this code can be simplified by using a library like web3 or ethers.js.
Once signed, MetaMask will broadcast the transaction automatically. The order state update listener will take over from here. Upon invoice payment, the progress bar will be set to 100%, the proof of payment will be populated, and the Start Another Swap
button will be visible.
NOTE: In a real application, the refund details should be provided to the user as a file download before they're allowed to fund the swap. This sample only demos the refund flow when navigating directly from a failed swap.
If REDSHIFT fails to pay the invoice, the user must be able to reclaim the funds that they sent to the swap contract.
Open the Refund page to view the sample refund flow.
In this example, the user is responsible for refund transaction submission. This is not strictly required. Any address is capable of signing and broadcasting the refund transaction. Regardless of who broadcasts this transaction, the funds will always be returned to the address that initially funded the swap. This could be used to submit the refund transaction on behalf of the user when the timelock expires, which offers a better UX.
We cannot allow the user to broadcast the refund transaction immediately following invoice payment failure. Any refund transaction mined before the block timelock is met will fail. The ether swap timelock is currently set to 480 blocks, which means that the user must wait roughly 2 hours before refund transaction submission.
To begin the process, we'll fetch the refund details using the order id of the failed swap:
The ether refund details contain the following information:
If blocksRemaining
is greater than 0 then we know that the refund transaction cannot be submitted yet. Instead, we'll display a block countdown to timelock expiration.
To accomplish this, we'll subscribe to the Ethereum block height using the REDSHIFT WebSocket API and update the UI when a new block is mined:
Once blocksUntilRefundable
is less than or equal to 0, we can enable the Get Refund
button and allow the user to submit the refund transaction.
From here, we use the same approach as the funding transaction. The refund transaction details are passed to the sendTransaction
RPC call and the progess bar is updated using the order state subscription. Upon refund confirmation, the progress bar will be set to 100% and the Start Another Swap button will be visible.
A Typescript gRPC client for LND with support for all LND sub-servers.
Originally forked from Matt-Jensen/lnrpc.
Auto-generates lnd/lnrpc clients and Typescript type definitions using a target release tag
Supports all LND sub-servers
Wraps requests in promises
Easily setup SSL and Macaroons
Instantiates all gRPC services
uint64/int64 types cast to string to prevent precision loss
Notes:
Ensure you have an lnd instance running with --no-macaroons
, unless you provide macaroon authentication to your lnrpc instance when created.
If you want to interact with the LND sub-servers, ensure that LND was compiled with the necessary sub-server build tags.
If the following error is thrown in the consuming application, run npm rebuild
:
This package exports a create function for the main gRPC server as well as each sub-server:
You can also import the create function for the main gRPC server using the default import:
If you want to interact with all servers, wrap the functions in a class or object for easy initialization:
Connecting to an lnd instance at localhost:10001
.
All main server (lnrpc) methods documentation can be found here.
By default lnrpc assumes SSl certificate pinning. In order to use lnrpc with a service (like BTCPayServer) which manages your certification, you'll have to opt to disable certificate pinning by passing { tls: false }
within your lnrpc configuration.
Clone Repository & Install Dependencies
Change LND gRPC release version
To change the gRPC definitions used for all auto-generated types and RPC methods edit the config.lnd_release_tag
value in package.json
to the desired LND release tag and run the following:
Newly generated type definitions will be available in ./generated
. You can now delete the old proto file inside the lnd directory. Use the generated type definitions to update the types in src/types/rpc
.
This project is licensed under the MIT License.
Quote Field
Description
orderId
A unique identifier for your order. This is required to execute a refund transaction in the event REDSHIFT fails to pay the invoice.
expiryTimestampMs
The timestamp in milliseconds that the quote will expire if the user does not take action. We use this value to implement the quote expiration timer in the app. The action required to stop the quote expiration timer varies based on the payment asset. For Bitcoin, the timer will stop once a funding transaction is seen in the mempool. For Ethereum assets, the timer will stop when a funding transaction confirms.
amount
The amount the user must pay denominated in the payment asset that they selected (tBTC or kETH in this sample).
details
Quote details that are specific to the chosen market.
unsignedFundingTx
The unsigned Ethereum funding transaction. When using metamask, this object can be passed directly into web3.sendTransaction
to initiate payment.
Update Type
Description
GeneralStateUpdate
This is the most basic state update, which contains the orderId
and state
. General state updates are returned when the update did not involve a transaction confirmation or invoice payment. Both TxConfirmedStateUpdate
and SwapCompleteStateUpdate
extend this type.
TxConfirmedStateUpdate
In addition to the orderId
and state
fields, this update type returns a transactionId
. This type is used when notifying the subscriber of a partial fund, fund, or refund transaction confirmation.
SwapCompleteStateUpdate
In addition to the orderId
and state
fields, this update type returns a preimage
. This type is used when notifying the subscriber of an invoice payment. The preimage
is the proof of payment.
Refund Field
Description
market
The market of the order, which contains the on-chain and off-chain asset tickers. ETH_LBTC
, for example.
state
The active order state. REDSHIFT will return refund details regardless of the order state. This field can be used in client-side validations to prevent the user from submitting a refund transaction for an order that's already complete or refunded.
blocksRemaining
The number of blocks remaining until the timelock expires and the refund transaction can be submitted.
refundableAtBlockHeight
The block height at which the timelock expires and the refund transaction can be submitted.
refundableBalance
The balance that is available for refund. Note that this field will not be decreased once the refund is complete.
details
This field contains the network-specific details that are necessary to submit the refund transaction. In this case, it contains two properties: to
and data
. These can be passed into sendTransaction
in the same way as the funding details to sign and broadcast the refund transaction.