SEP: 0025
Title: New account deposit
Author: @msfeldstein
Track: Standard
Status: Draft
Created: 2019-10-29
Discussion: https://github.com/stellar/stellar-protocol/issues/446
Anchors and other businesses (Providers) need a way to help their users (Clients) accept assets whether or not the client already has a Stellar account, and whether or not it is funded or has a trustline. Current account creation and trustline setup is complicated and can be a multi-step synchronous process.
The current solution to depositing an asset in a new users account is as follows
- Create a stellar account in their wallet
- Somehow acquire lumens to fund and open the account
- Open a trustline for the asset
- Provider sends payment
This has a few points of failure, and the burden of asking clients to acquire lumens is too high.
The proposed solution operates by the provider creating a holding account that the clients key can sign for to claim the assets in the holding account. Once this holding account is created, the assets effectively belong to the client as they're controlled by their key, and their key only. The wallet application will watch for accounts it can claim, and either automatically, or with user consent, merge the holding account and all its assets into the main account to finalize the payment.
There are two sides to this protocol, the provider and the client.
After negotiating the off-chain deposit details, the Provider will create the holding account, fund it with the tokens, as well as enough lumens to cover the necessary operations. It then removes the accounts signing power, replacing it with the clients account so only the client's private key can use the holding account. The provider may listen for operations on the holding account if it wants to keep bookkeeping on the state of the holding account, to verify it got merged properly.
# Providers Transaction:
Create the holding account. HOLDING_LUMENS has to be at least 2 xlm in order to accommodate two entries, one for the extra signer, one for the trustline. If providers would like be responsible for the balance required to establish the trustline for clients' accounts, HOLDING_LUMENS has to be at least 2 + 0.5 xlm + small amount of transaction fee.
createAccount
destination: "<HOLDING_ACCOUNT_ID>"
startingBalance: "<HOLDING_LUMENS>"
----------
Adding the trustline to the intermediate account
changeTrust
asset: {"code":"ABC","issuer":"<ISSUER_ACCOUNT_ID>"}
amount: "100"
source: "<HOLDING_ACCOUNT_ID>"
----------
Sending the assets to be transfered into the intermediate account
payment
destination: "<HOLDING_ACCOUNT_ID>"
asset: {"code":"ABC","issuer":"<ISSUER_ACCOUNT_ID>"}
amount: "<FINAL_AMOUNT>"
----------
Removing the anchors signing power over the intermediate account, and replacing that signer with the final destination account
setOptions
source: "<HOLDING_ACCOUNT_ID>"
masterWeight: 0
signer: {"ed25519PublicKey":"<CLIENT_ACCOUNT_ID>","weight":1}
At the same time, the client will use Horizon's Accounts for signers endpoint to listen for new accounts the client can sign for. Once the providers transaction completes, the client will find the holding account, and claim the assets within using the transaction below.
# Clients Transaction:
Create the clients account
createAccount
destination: "<CLIENT_ACCOUNT_ID>"
startingBalance: "1.0"
----------
The main account needs a trustline. We need to ensure it has enough lumens for one trustline and is able to make transactions so we give it 0.51 xlm
payment
asset: {"code":"XLM"}
amount: "0.51"
source: "<HOLDING_ACCOUNT_ID>"
destination: "<CLIENT_ACCOUNT_ID>"
----------
Add the trustline to the main account to enable the following payment of the asset
changeTrust
asset: {"code":"ABC","issuer":"<ISSUER_ACCOUNT_ID>"}
source: "<CLIENT_ACCOUNT_ID>"
----------
Move the actual assets from the intermediate account into the main account
payment
asset: {"code":"ABC","issuer":"<ISSUER_ACCOUNT_ID>"}
destination: "<CLIENT_ACCOUNT_ID>"
amount: "<FINAL_AMOUNT>"
----------
Remove the trustline of the asset from the intermediate account so it can be merged to the main account
changeTrust
asset: {"code":"ABC","issuer":"<ISSUER_ACCOUNT_ID>"}
limit: "0"
----------
Merge the intermediate account into the main account to absorb any leftover lumens
accountMerge
destination: "<CLIENT_ACCOUNT_ID>"
----------
This SEP is designed to separate the intentions of the Provider sending the assets, and the ability of the client to receive them. After the Providers step is completed, they've effectively given the assets to the Client, as the assets are now under full control by the clients private key.
This SEP may be either redundant or updated when CAP-23 is finalized and implemented, allowing for more explicit claimable balances in a less complicated fashion.
Wallets will need to be clear in their UI about the user wishing to claim any holding accounts. It needs to be known that the client wishes to claim the accounts either by the client completing an initial deposit flow in the wallet, or by providing a confirmation UI for the client to claim any available accounts it can sign for. The wallet should not automatically claim any accounts without a clear indication from the user that they intend to.
There are various approaches to satisfy the minimum lumen balance of the holding account. In situations where a provider chooses to convert some of the sending asset into xlm to account for the minimum balance of the holding account, the value of sending asset has to be greater than the minimum lumen balance of the holding account, which is at least 2 xlm in the case of it having one trustline and one receiver (signer).
- https://github.com/msfeldstein/airdrop-script
- [Add reference server and demo client PRs]