Path Payments - Stellar
Welcome
Hi, nice to meet you. Wishing you and yours a prosperous 2023.
Well, my first technical post is a note on using “Path Payment Strict Send/Receive” operation in Stellar Network.
First, a conclusion
When using “Path Payment Strict Send/Receive” Operation, it is possible to relay non-authorization Assets. Of course, “Path Payment Strict Send/Receive” will target assets that are offered as offers.
So if offers are created, even assets for a limited account could be executed in an outside account.
Why?
“Path Payment Strict Send/Receive” operation allows the asset output from the execution of an offer to be used as input for another offer. This works like a Unix Pipeline. And the execution of this series of offers is a consistent processing, just as in a relational database transaction.
In other words, TrustLine is a restriction on whether assets can be held, not whether assets are transferable.
Example
There are two offers:
1: buy Asset:A - sell Asset:B
2: buy Asset:B - sell Asset:C
You have not established only a TrustLine for Asset:B, but "Path Payment Strict Send" operation can be used to exchange Asset:A to Asset:C.
The program code for this process is listed at the bottom of the article.
Remarks
Soroban is getting a lot of attention and it is going to be a great year for Stellar.
As a developer myself, I am looking forward to it.
Let’s get Soroban-ing!!
Please check the official website for all accurate information about Stellar.
Sample code by Ruby
I'm Japanese, so I support Ruby!
require 'stellar-sdk'
Client = Stellar::Client.default_testnet
# create issuer
Issuer = Stellar::KeyPair.random
Client.friendbot(Issuer)
# define assets
AssetA = Stellar::Asset.alphanum4(?A, Issuer)
AssetB = Stellar::Asset.alphanum4(?B, Issuer)
AssetC = Stellar::Asset.alphanum4(?C, Issuer)
# manage offers
Client.horizon.transactions._post(tx:
Stellar::TransactionBuilder.new(
source_account: Issuer,
sequence_number: Client.account_info(Issuer.address).sequence.to_i + 1
)
.add_operation(
# buy Asset:A - sell Asset:B
Stellar::Operation.manage_buy_offer(
buying: AssetA,
selling: AssetB,
amount: 100,
price: 1
)
)
.add_operation(
# buy Asset:B - sell Asset:C
Stellar::Operation.manage_buy_offer(
buying: AssetB,
selling: AssetC,
amount: 100,
price: 1
)
)
.set_timeout(600).build.to_envelope(Issuer).to_xdr(:base64)
)
# create trader
Trader = Stellar::KeyPair.random
Client.friendbot(Trader)
# change trustline without Asset:B
Client.horizon.transactions._post(tx:
Stellar::TransactionBuilder.new(
source_account: Trader,
sequence_number: Client.account_info(Trader.address).sequence.to_i + 1
)
.add_operation(
# for Asset:A
Stellar::Operation.change_trust(asset: AssetA)
)
.add_operation(
# for Asset:C
Stellar::Operation.change_trust(asset: AssetC)
)
.set_timeout(600).build.to_envelope(Trader).to_xdr(:base64)
)
# payment seed Asset:A
Client.horizon.transactions._post(tx:
Stellar::TransactionBuilder.new(
source_account: Issuer,
sequence_number: Client.account_info(Issuer.address).sequence.to_i + 1
)
.add_operation(
Stellar::Operation.payment(
destination: Trader,
amount: [AssetA, 100]
)
)
.set_timeout(600).build.to_envelope(Issuer).to_xdr(:base64)
)
# check
puts 'Before'
Client.account_info(Trader.address).balances.each { |balance|
puts " Asset:#{balance['asset_code']} = #{balance['balance']}" if [?A, ?C].include?(balance['asset_code'])
}
# path payment Asset:A to Asset:C
Client.horizon.transactions._post(tx:
Stellar::TransactionBuilder.new(
source_account: Trader,
sequence_number: Client.account_info(Trader.address).sequence.to_i + 1
)
.add_operation(
Stellar::Operation.path_payment_strict_send(
destination: Trader,
with: [AssetA, 100],
amount: [AssetC, 100],
path: [AssetB]
)
)
.set_timeout(600).build.to_envelope(Trader).to_xdr(:base64)
)
# check
puts 'After'
Client.account_info(Trader.address).balances.each { |balance|
puts " Asset:#{balance['asset_code']} = #{balance['balance']}" if [?A, ?C].include?(balance['asset_code'])
}
Discussion