Atomic Swaps

How to create atomic swap transactions

The process of atomic swaps entails the utilization of partially signed components from both parties, and completion occurs only after both parties have signed all the necessary pieces. With this SDK, there are two methods available to accomplish an atomic swap transaction: a two-step and a three-step approach.

To begin with, let's examine the two-step method provided by the SDK, which involves utilizing two functions, namely "stasCreateSwap" and "stasAcceptSwap."

Two step swap

The stasCreateSwap function requires the user to input a UTXO that they are willing to swap for something else, which can either be a STAS token or native BSV. The user must also specify the output they desire to receive as a result of the atomic swap transaction, which can also be either a STAS token or native BSV output.

To define the output, the SDK utilizes an object known as wantedData, which comprises the following fields:

const wantedData = {
    satoshis :  number
    script :  scriptHex // optional if STAS script
}

In the event that only the value of the satoshis field is provided, stasCreateSwap will create a native BSV output to the address from input #0. However, if the user desires a specific STAS token for the atomic swap, the script field must be supplied with the hexadecimal representation of the token script.

const offerHex = await stasCreateSwap.signed(
    ownerPrivateKey, 
    utxo, 
    wantedData
)

The subsequent step involves finalizing the atomic swap transaction by adding the remaining inputs and information required to generate the unlocking scripts. In the stasAcceptSwap function, the following core arguments are required, and we will examine each one in this example:

  • offerTxHex: This represents the hexadecimal form of the transaction from the stasCreateSwap function.

  • ownerPrivateKey: This refers to the private key of the UTXO's owner who is participating in the atomic swap transaction.

  • makerInputTxHex: This denotes the complete transaction hexadecimal of the input #0 in the offerTxHex.

  • takerInputTxHex: This represents the complete transaction hexadecimal of the UTXO that is being utilized to complete the atomic swap transaction.

  • takerVout: This refers to the output index of the UTXO being used to complete the atomic swap transaction.

  • paymentPrivateKey: This denotes the private key of the UTXO's owner who is paying the transaction fee.

  • paymentUtxo: This represents the UTXO that is being used to pay the transaction fee.

const swapHex = stasAcceptSwap.signed(
    offerTxHex, 
    ownerPrivateKey, 
    makerInputTxHex, 
    takerInputTxHex, 
    takerVout, 
    paymentPrivateKey, 
    paymentUtxo,
    additionalOutputs // optional
)

more on additionalOutputs soon... After executing the function, you will receive a transaction hexadecimal representation that is now ready to be broadcasted to the miner. The final outcome of the transaction will be that input #0 will transfer ownership to output #1, while input #1 will transfer ownership to output #0, in accordance with the terms of the atomic swap transaction.

Three step swap

To make this a three step swap we can simply create the offer hex with the unsigned function call as follows:

const unsignedOfferHex = await stasCreateSwap.unSigned(
    ownerPublicKey, 
    utxo, 
    wantedData
)

When the unsigned function call is made, the returned object will contain the transaction in the "tx" field, which can be converted to a string to obtain the hexadecimal format. In this scenario, input #0 will not be signed. After the stasAcceptOffer function has returned the "swapHex" value, it can then be used to sign the transaction and send it back to the offer hex creator.

An additional argument must be included, which is the complete transaction hexadecimal representation of the taker, which corresponds to input #1 in the unsigned swap hexadecimal.

const signedSwapHex = await stasSignSwap.signed(
    unSignedSwapHex, 
    ownerPrivateKey, 
    takerInputTx
)

After executing the function, you will receive a transaction hexadecimal representation that is now ready to be broadcasted to the miner.

Additional outputs for atomic swaps

During the second step of the atomic swap transaction, it is possible to include additional outputs. This can be accomplished by adding an array as an additional function argument to specify the amounts and addresses to which the extra funds will be sent. It is important to note that for additional outputs, the funds must originate from input #1 UTXO in the atomic swap. Consider the following example:

Output #0 requests 1000 Native satoshis

const wantedData = {
    satoshis: 1000
}

Additional outputs are added as follows:

const additionalOutputs = [ 
    {
        address : "some address string",
        satoshis : 1000
    },
    {
        address : "some address string",
        satoshis : 1000
    }
]

In this case the input #1 needs to contain exactly 3000 in native satoshis to complete this transaction. This can also be done using STAS tokens where the property of the token is splittable and the total input #1 amount in satoshis is equal to the output #0 amount plus any additional output amounts if applicable.

Last updated