All API requests that create a new transaction will accept an optional referencedTransactionFullHash parameter which creates a chained transaction, meaning that the new transaction cannot be confirmed unless the referenced transaction is also confirmed. This feature allows a simple way of transaction escrow:
- Alice prepares and signs a transaction A, but doesn't broadcast it by setting the broadcast parameter to false. She sends to Bob the unsignedTransactionBytes, the fullHash of the transaction, and the signatureHash. All of those are included in the JSON returned by the API request. (Warning: make sure not to send the signed transactionBytes, or the signature itself, as then Bob can just broadcast transaction A himself).
- Bob prepares, signs and broadcasts transaction B, setting the referencedTransactionFullHash parameter to the fullHash of A provided by Alice. He can verify that this hash indeed belongs to the transaction he expects from Alice, by using Calculate Full Hash, which takes unsignedTransactionBytes and signatureHash (both of which Alice has also sent to Bob). He can also use Parse Transaction to decode the unsigned bytes and inspect all transaction fields.
- Transaction B is accepted in the unconfirmed transaction pool, but as long as A is still missing, B will not be confirmed, i.e. will not be included in the blockchain. If A is never submitted, B will eventually expire -- so Bob should make sure to set a long enough deadline, such as the maximum of 32767 minutes.
- Once in the unconfirmed transactions pool, Bob has no way of recalling B back. So now Alice can safely submit her transaction A, by just broadcasting the signedTransactionBytes she got in the first step. Transaction A will get included in the blockchain first, and in the next block Bob's transaction B will also be included.
Note that while the above scheme is good enough for a simple escrow, the blockchain does not enforce that if A is included, B will also be included. It may happen due to forks and blockchain reorganization, that B never gets a chance to be included and expires unconfirmed, while A still remains in the blockchain. However, it is not practically possible for Bob to intentionally cause such chain of events and to prevent B from being confirmed.