How to set up deposits and withdrawals on Stellar?
Today, stellar is among the top blockchain platforms across the globe. It allows its users to issue assets and connect them to existing banking rails or networks to move value onto the network or off of it. These connections are created by services known as “Anchors”. Most anchors set up the infrastructure on Stellar by following the best practices defined in SEPs to authorize wallets for offering in-app withdrawals and deposits.
Stellar Ecosystem Proposals (SEPs) are open-source documents that are publicly created to specify how interactions and interoperation must take place among different institutions, like asset issuers, exchanges, wallets, and service providers. SEP-24 is the one that defines the specifications for deposits and withdrawals. It allows the deposits and withdrawals of cryptocurrencies like ETH, BTC and ERC20 tokens like USDT. SEP-24 also requires SEP-1 (links meta-information to organizations and assets) and SEP-10 (creates authenticated user session).
Cooperation between the wallet and anchor applications is required to support deposits and withdrawals of an asset on/off Stellar. Hence, in this article, we will discuss the necessary steps required for building a SEP-24 server so that users can set up deposits and withdrawals on Stellar.
But before we begin with the steps, let us briefly understand how deposits and withdrawals work on Stellar with the help of an example.
How to set up deposits and withdrawals on the Stellar blockchain?
David is a customer who wants to deposit an asset on the stellar network. This is how the procedure will proceed:
- David will open the SEP-24 wallet application of his choice on his device.
- Once he selects an asset to deposit, either the wallet will find an anchor, or David can choose a specific anchor.
- After the wallet authenticates with the anchor, he will enter his KYC and transaction information as the anchor requests.
- The wallet will provide instructions, following which he will deposit real fiat currency with the anchor (e.g., he may make a bank transfer).
- Once the wallet receives his deposit, he will receive the tokenized asset from the anchor’s distribution account on the Stellar network.
David can use the digital asset on the Stellar network for several use cases like payments, remittances, trading, store of value, etc.
In the future, if David wants to withdraw his assets from the Stellar network, this is how he will proceed:
- He will open his wallet application, select the asset for withdrawal and his wallet will find the anchor.
- After it authenticates with the anchor, the wallet will open the given interactive URL and allow David to enter his transaction information (KYC has already been collected)
- The wallet will ask for his approval and send the specified amount of his asset balance to the anchor’s distribution account on Stellar
- Once the anchor receives the payment, David will receive the withdrawn funds via bank transfer.
Before we begin with the setup steps, let’s discuss a few tools and references offered by the Stellar Development Foundation (SDF) to simplify server implementations.
Tools and References
To handle deposits and withdrawals, you will have to set up and launch a test server and a production server. While we will cover all the necessary steps in this article, you must consider that the SDF offers some tools that simplify the implementation of these servers and test them from the client-side. So, you don’t always have to start from scratch:
- Anchor Server Reference Implementation: Polaris is an extendable Django reusable app created by SDF in Python to modularize the parts of the codebase that interface with the stellar network and provide clear methods to integrate your deposit & withdrawal forms, KYC process and banking rail connections.
- Demo Client & Deployed Example: SDF maintains a Demo Wallet Project to simplify the testing of your implementation on both testnet and pubnet. You can run these tests with a UI without setting up a new hosting infrastructure and get a clear visual example of how the functionalities work step by step, along with other insightful information.
- Anchor Validation Suite: It is a set of tests that helps to confirm if your anchor implementation complies with the latest SEP-24 standard specifications or not.
Now, let’s begin with the steps required to set up deposits and withdrawals on Stellar.
Set Up a Test Server
Before setting a server that connects with live banking rails and real money, building a test rig connected to the Stellar test network is always helpful.
There are a few prerequisites that need to be fulfilled before you start building infrastructure to connect a Stellar-network token to banking rails:
- Issue an asset on the network
- To ensure that wallets know where to find the server and relevant endpoints, add meta-information about the asset and define the location of your TRANSFER_SERVER_SEP0024 in your stellar.toml so that wallets know where to find the server and relevant endpoints.
Once you’ve taken these steps, you’re ready to begin with the setup.
Step 1: Implementing the /info Endpoint
The /info endpoint has several purposes, such as:
- It allows anchors to communicate basic information to wallets.
- It responds to client queries with a JSON object detailing the anchor’s supporting currencies for deposit and withdrawal.
- It allows anchors to communicate basic information to exchange interfaces and other Stellar apps.
- It lays out the fee structure for each currency.
Generally, anchors structure fees either as “fixed fees” (i.e,. a fixed value that is applied to the transactions) or a “fee percentage” (i.e,. a percentage of the transaction value). The /info endpoint can convey these structures directly as they are very straightforward. However, if you want to use a more complicated fee structure, you must use the /fee endpoint and indicate it’s enabled in the /info response.
Step 2: Authentication
Anchors, also known as on/off ramps, can authenticate individuals with their Stellar accounts. It eliminates the need to require usernames and passwords and providers a simpler experience to the wallet users.
Stellar Web Authentication verifies the user and creates a persistent session for them. It is a protocol to check if the Stellar private key for a given account is controlled by the said user or not. It uses Stellar transactions to encode challenges and responses as it relies on a variation of mutual challenge-response. This is how it works:
- A “challenge” transaction is requested by the client
- The only required information is the client’s public key, which is passed as the account parameter to request a challenge.
- The asset issuer provides the “challenge” transaction.
- It is signed by the client on the user’s behalf using standard Stellar SDK tools and returned to the issuer.
- After checking the validity of the signature, the issuer issues a JSON Web Token (JWT), which can be created with any existing JWT library.
- The JWT is a reusable key that the asset issuer signs to ensure validity. It allows the client to perform actions on the user’s behalf.
The JWT includes fields like:
- The sub key which contains the account of the authenticated user
- The exp key, which contains the expiration of the JWT
- Other keys which can contain any claim or data according to the Anchor’s wishes
The sub field contains the address of the authenticated user, which may act as a username. The JWT authenticates the said user.
Step 3: Deposit Flow
The deposit flow is the on-ramp to the Stellar network. Here, users can transfer funds via local rails to a stablecoin issuer for the transferred funds’ digital version.
Deposit flows entail a back-and-forth between an issuer’s server and a wallet’s client. It starts with polling the /info endpoint and setting up an authenticated user session by the wallet.
The POST /transactions/deposit/interactive Endpoint
The wallet POSTs to the /transactions/deposit/interactive endpoint to start a new deposit transaction. It informs the issuer of:
- The user’s Stellar account using the account parameter
- The type of asset to be deposited by the user via the asset_code parameter
Initiate Interactive Flow
The interactive flow involves the anchor’s server responding to the wallet’s PPOST with the interactive customer information needed response (a JSON object consisting of the URL used by the wallet to open an issuer-hosted web app).To collect the required information for completing a deposit, the issuer uses an issuer-hosted web app because the wallets can’t predict the information that an issuer will need. The web app is an interface that gathers information needed from the user, including KYC requirements and deposit information.
In case of authentication requirements, the server hosting the interactive flow usually handles it before initiating the deposit using a one-time-use JWT. However, if you use Polaris, you don’t have to worry about the authentication.
Returned by the /transactions/deposit/interactive endpoint, the more_info_url is crucial for completing deposits requiring a bank transfer. After the interactive flow, the wallets open it automatically to gain the bank account’s information to which the user needs to transfer the funds.
The more_info_url is relative to a single transaction. It is used throughout the endpoints for users to get more data on that specific entry.
The /transaction and /transactions endpoints allow wallets to gain information about:
- Status of a single transaction
- All of the user’s account’s transactions to show a historical view of operations
While waiting for a transaction’s status to change, wallets poll the /transaction endpoint to notify the user of the successful withdrawal. After the transaction’s completion on the Stellar network, its status will update from “pending_stellar” to “completed.” This endpoint should return a single JSON object representing the specified transaction and accept a particular transaction’s various identifiers.
The /transactions endpoint is required by wallets to access the user’s account’s transactions to display history. To ensure that a transaction was successfully created, wallets can use this endpoint after making a POST request to /transactions/deposit/interactive. This endpoint should accept a number of parameters for filtering the transactions returned in the response. Also, JSON object representation of a specific transaction must be the same in response to both /transaction and /transactions.
Step 4: Withdrawal Flow
As deposit flow is the on-ramp to the Stellar network, withdrawal flow is the off-ramp. To return digital assets, the user makes a payment on the network and, in return, receives the equivalent value in fiat currency in their bank account from the anchor.
Like deposit flows, withdrawal flows entail a back-and-forth between an issuer’s server and a wallet’s client.
Once the wallet is done with the polling of the /info endpoint and set up of an authenticated user session, it makes a POST request to the issuer’s /transactions/withdraw/interactive endpoint to initiate a withdrawal. This action creates a new, incomplete transaction record in the issuer’s database. The issuer’s response must contain the transaction’s ID and the URL to begin the interactive flow. For security reasons, you shouldn’t include the SEP-10 JWT token in the URL for authentication.
For authentication, users of Polaris don’t have to worry as it adds a short-life JWT token to the URL and uses it along with session cookies to authenticate the user. For non-users of Polaris, their own authentication mechanisms can be implemented.
Then, the web app collects the necessary information for completing the transaction. For a withdraw query, the only necessary parameter is asset_code; however, another notable parameter is lang. It can be used on both the deposit and info endpoints.
There are three separate phases of UI pages served to the user going through the withdrawal flow:
- Mocked KYC: The anchor may be obligated legally to collect certain data from the user at the beginning of the withdrawal. Users need to understand relevant legal requirements before implementing this phase.
- Withdrawal information: The issuer is required to collect the asset’s numerical amount that has to be transferred, along with some other pieces of the necessary information.
- Waiting for transfer: The last page rendered in the process is about making a postMessage call to the Wallet, notifying it that it has all the required information.
After all of this is done, the wallet submits the transaction to the Stellar network. It transfers tokens from the user to the issuer via their Stellar accounts. Then, it begins polling the issuer’s /transaction endpoint until the relevant transaction has the expected status, i.e. “complete.”
The issuer should detect that the wallet has submitted a withdrawal transaction, after which they should mark it as “complete” in case of success and “error” in case of a problem.
Set Up a Production Server
After you’re done testing deposit and withdrawal flows, you can start with the real deployment after performing a full security audit to ensure there aren’t any vulnerabilities present.
Step 1: Deploying a Secure Environment
The following steps can help you to deploy a secure environment:
- Keep the test server up.
- Deploy the production system (mainnet) in a separate environment.
- If you have a big team working on the codebase, you can issue a third staging environment.
- Follow best practices for asset issuance if you’re issuing your asset along with offering an on/off-ramp.
- Create separate distribution and issuing accounts before distributing real assets on the public network.
- Highly secure the issuing account’s secret key (via cold storage, multi-signature, etc.)
- Your server will use the distribution account to send/receive assets programmatically; hence it should only have the minimum balance required to keep the operations running for a short time period.
- Small amounts of an asset should be sent by the issuing account to the distribution account frequently to represent an expected deposit volume for a given period.
Step 2: Connecting to Real KYC
To ensure compliance with local regulations before honoring deposits and withdrawals, most anchors must collect KYC information, such as the user’s name, email, age, government-issued ID number, etc. Handling KYC is totally up to you; however, these requirements differ from one jurisdiction to another. Hence, you must find a country-specific KYC provider.
You should link the KYC information to the session created through Stellar Web Authentication and to the user so that it doesn’t have to be entered again and again.
To ensure a good UX and increase the KYC conversion rate, you should:
- Make the error and validation messages clear
- Include instructions for what to do
- Localize messages based on the user’s language and location
Step 3: Pre-Filling the KYC Form
Pre-filling the KYC form to reduce the friction of getting started is a great way to begin the process. The anchor can provide the KYC form with the user’s values previously sent by the wallet in /transactions/withdraw/interactive and /transactions/deposit/interactive endpoints. You should also allow the pre-filled fields to be editable for users.
Step 4: Connecting to Real Banking Rails
Fiat-backed token issuers should have a full reserve, implying a 1:1 relationship between the money in the bank and Stellar network tokens. Each fiat token on the Stellar network is backed by an underlying real-world asset and can be redeemed for it as well. Hence, their issuers must connect to real banking rails to validate user deposits and complete user withdrawals.
To identify and fetch a user transfer, issuers usually take the following approaches:
- API Polling: They fetch the bank’s API via a cron job to check the updated status of the transfers sent from and received by the issuer’s bank account. After identification and confirmation of a new transaction by the system, digital funds can be sent to the user’s account.
- Webhook: Although the leanest approach in back-end logic, not all banking rails support this option. Here, after receiving a new transfer, the bank proactively hits an issuer’s endpoint and updates that information on the issuer’s database. Then, the issuer can match that transaction to an existing in-process deposit and validate that the user can receive their digital funds.
You should ensure a full security audit on your systems after putting the banking rails connections in place. Some anchors also add a manual final step before approving withdrawal transfers for better security. However, this step is only relevant as long as the wait time aligns with user expectations and doesn’t affect the user experience negatively.
Step 5: Testing Edge Cases
It is always helpful to test different scenarios and edge cases once your application becomes fully functional to ensure that your system’s behavior matches the expectations.
Here are a few testing suggestions:
- Ensure that the interactive interface follows Stellar’s UX Guidelines.
- Test the interactive flow usability on both small and large screens.
- Test the interface using different locale information, and verify the translated content.
- Make sure that the issuing account is set up with the right home domain. The website has branding visuals, clear language telling users how to report problems, content about your company, and a method for contacting you to seek support.
- Ensure that KYC appears with a new wallet SK.
- See that you can go through KYC multiple times with the same Stellar SK.
- Verify that KYC is not appearing when using a previous wallet SK.
- Ensure that the error messages are comprehensible.
- Check that KYC doesn’t accept wrongly formatted inputs.
- Verify that you can use the same KYC information (email, phone number, username, etc.) several times.
- Ensure that deposits are disabled for very small and very large values.
- Make sure that all deposit response params conform to protocols.
- Verify that the deposit flow goes through and the banking rails are working.
- Ensure that if the JWT token is missing, the endpoint returns an error.
- Ensure that withdrawals are disabled for really small and really large values.
- Ensure that you cannot make a withdrawal of value higher than the current balance.
- Make sure that all withdraw params conform to protocols.
- Verify that the withdraw flow goes through and the banking rails are working.
- Ensure that if the JWT token is missing, the endpoint returns an error.
- Make sure that the /transaction endpoint is working for a newly created transaction.
- Ensure that the /transaction endpoint returns all transactions from a specific user.
- Verify that the /transaction endpoint is working for a completed transaction.
- Check that the distribution is done via an exclusive distribution account and not an issuing account.
- Make sure that market making is done through a dedicated account instead of an issuing account.
- Ensure that all authenticated endpoints are not accessible without the JWT tokens.
Now that all specifications have been done and set up, you should prepare for the launch.
Step 1: Polishing and Internationalization
In your web app, you can support multiple languages with the help of the Accept-Language language parameter from the http request headers for localized content and enabling users to change it conveniently. You can also show a language selection screen to the user at the beginning of the deposit and withdrawal processes.
Available support for two languages (English and the fiat currency country language) is beneficial as:
- It empowers users to have a seamless experience while navigating through screens.
- It supports international institutions like wallets that require product testing before beginning with new integrations.
It is beneficial to have a group of beta testers because:
- You can check if any edge cases require polishing.
- You can ensure that your system is working well with a variety of user inputs.
Beta tests using a soft launch stage can be done before beginning the procedures of marketing and distribution. You must also document the testing process with screenshots and videos for the purpose of:
- Providing potential users with clarity and confidence in the product.
- Future security audits.
- Providing new partners with confidence and clarity of the product.
Step 2: Market Making
As soon as your asset is available for in-app withdrawals and deposits, users buying and selling orders will begin to fill up their order book. Hence, it is essential to ensure that you have a healthy market with a deep set of orders on both sides to ensure that these orders have liquidity.
Kelp, a free trading bot maintained by the Stellar Development Foundation, supports several trading and market-making strategies. It automates the order placements, following which you can track your token market’s health with parameters like:
- Bid/Ask Amounts: Both sides of the order book must have at least USD 25000
- Spread Size: The average price of the bids and asks must be within 4% of each other
As the value of big/ask amounts is relative to the anchor, it should increase as the total supply and traded assets grow.
Step 3: Creating an Anchor Website
To ensure a clear connection between the Stellar asset and the URL, your issuing account should link to a website that allows wallets and consumers to:
- Find information about your team.
- Get in touch with you for feedback and queries.
- Gain information about how your services work.
The following requirements will ensure that your users have a great experience while navigating through your website:
The branding of your webpage will ensure that your users feel that they are in the company’s domain. Hence, your brand universe should have several aspects, such as:
- Your company’s logo
- Your slogan
- Uniform colors
- Uniform fonts and icons
Your company’s description plays a vital role in bringing in users and increasing conversions as it provides them with information to help them decide if they can trust your service and hold your asset or not. Hence, your company description should be very clear, including aspects like:
- Description of your business
- Information about your mission
- Your vision’s outline
- Information about your executive team
- How you are integrated with the Stellar networks
- With which wallets you are integrated
- What your asset represents
- Information about how your asset is backed and how users can redeem it
It shows users that your system is reliable, and it conforms to the best protocols and practices of the financial industry.
Adding a FAQ section and a contact email for customers to report inconsistencies, get in touch and get support is an essential addition to your website. You must clearly state the procedure to get in touch with your support team for users.
Step 4: Connecting to Wallets
Anchors need to connect to wallets as all anchor user interactions are done through it. Connecting to wallets with a good market penetration is beneficial.
Connecting to wallets is simple as both ends of the integration already comply with the SEPs. Stellar.org maintains a list of wallets, including the ones which currently support SEP-24. You can send them a message with more information on an issuer account and an asset to get some real users to the anchor.
Stellar is an impeccable and highly functional blockchain platform that offers multiple beneficial opportunities to its users. The ability to set up deposits and withdrawals on the platform is one such opportunity. However, although the process is simple, it is highly technical and requires expert supervision for seamless proceedings.
If you are looking for a partner to set up deposits and withdrawals on Stellar, feel free to contact our skilled Stellar blockchain developers and team for expert guidance.
Start a conversation by filling the form
All information will be kept confidential.