Introduction to payments in Stellar
Learn the essentials of the Payment operation in the Stellar network
Last updated
Learn the essentials of the Payment operation in the Stellar network
Last updated
If I wanted to pay someone, the easiest way would be to hand them cash, itโs immediate and free, no one charges me for making that payment, even a bank transaction is quite quick and free of charge. But what if I want to send money abroad? What if I want to send it in one currency and have the receiver get it in another?
Letโs say someone in the United States wants to deposit dollars, and someone in Argentina wants to receive pesos. The first issue is that banks in different countries donโt operate on the same network, so they canโt transfer money directly. This requires some form of shared ledger.
When it comes to currency exchange, banks use their accounts in banks located in the other country. They have deposits in the local currency and transfer money to the recipient as if it were a domestic transaction. In this process, the intermediary account, called a "nostro" account by the originating bank (since it is their own) and a "vostro" account by the receiving bank (since it belongs to another bank), is crucial.
Additionally, there are numerous bureaucratic procedures to comply with the regulatory framework of the other country, such as anti-money laundering laws and tax evasion regulations. This adds more participants, costs, and time. Something that could take seconds might take several days.
At the very least, making an international payment is a complex task.
And this is assuming that both the sender and the receiver have bank accounts, which isnโt the case for many people. In 2022, it was estimated that 1.4 billion people did not have formal access to financial services like bank accounts.
Stellar simplifies this process significantly. First, because blockchain technology transcends borders; second, the payment is completed in secondsโthe time it takes to close a block; and third, thanks to the native exchange, the conversion between assets is handled automatically by the blockchain.
For example, a user could pay dollars to an anchor to receive USDC on Stellar, then make the payment to the recipient's account, who would receive pesos (or whatever currency they prefer) through the native exchange. If the recipient wants to cash out, they could go to a local anchor to exchange digital pesos for fiat currency.
Stellar supports several types of payments, including regular payments, Claimable Balances, and Path Payments, which allow payments to be made in one currency and received in another using the native exchange. In this article, we will focus on the first two types.
The theory is simple, the Payment operation transfers some asset amount from one account to another. Lets explore this operation with a minimalist example:
Let's break it down.
Here, we create a server
object and pass it the Horizon URL (remember, this is the API we use to interact with the network). In this case, it is the Testnet. This server
object is the one that knows how to interact with Horizon, which is Stellarโs API.
Keep in mind that to interact with the network, you need to install the stellar-sdk
. Next, we create a keypair
object from the secret key of the source account. The data structure account will be covered in another blog post. For now, you need to know that itโs an object that knows the public key and the secret key of the account. Weโll use this Sender account as the source of the payments, and incidentally, it will also pay the transaction fee. We also define the public key of the recipient of the payment funds:
Here, we then create an AccountResponse
object, which contains information about the account, such as the sequence number we need to assemble the transaction:
Then, we create a transaction object where we specify the source account of the transaction. We pass an object with options, which in this case includes properties like the maximum fee we are willing to pay for the transaction (measured in stroops), and a string that is the network passphrase used to validate the transactionโs signature. As there are several networks in Stellar, and if we sign a transaction with mainnet account credentials and send it to the testnet (or vice versa), it will throw an error.
Next, we add operations to the transaction. In this case, we add only one, but each transaction can have up to 100 operations. We define the operation earlier with Operation.payment. We also specify the payment destination, the asset (in this case, lumens), the amount (in this case, in whole numbers, not stroops), and optionally, the source account for the payment. If we donโt specify it, as in this case, the default is the source account of the transaction.
With setTimeout
, we indicate the number of seconds in which the transaction is valid. If sent after that time, the transaction fails. Lastly we use .build()
to construct the transaction and increment the sequence number. Finally, we sign the transaction with the keypair object that has the secret key.
Finally, we send the transaction with the server
object created before:
Claimable balances are operations designed to split a payment into two stages, both of which need to be sent to the blockchain.
First, the account that's sending the payment sets up the claimable balance. At this point, the payment amount is no longer shown in the sender's account balance, nor in the recipient's account. Instead, it is reserved in its own claimable balance data structure.
Example of an operation for creating a claimable balance:
To check the status of the claimable balance you can do it like so:
The second stage is when the recipient claims the balance. Once claimed, the funds become available in the recipient's account:
(the balanceId
is hardcoded for demonstration purposes)
Claimable balances support both absolute and relative time conditions for claiming. Combined with logical operators such as NOT, AND, and OR, you can create restrictions like:
Not before one month from the creation of the claimable balance
Not before 1 hour and no more than 24 hours
Before 10 days or after 20 days
Unconditional