Skip to main content

Making Your Wallet SDP-Ready

Remember that any SDP instance will need an agreement with a wallet provider before sending disbursements into that wallet. This ensures the wallets are comfortable receiving funds from your organization and governs any commercial arrangement between the organizations. The wallet will need to allowlist the SDP domain before the SDP can send disbursements to that wallet. When the wallet domain is added to a SDP, it's effectively being allowlisted by the SDP. Both sides listing the other allows them to retrieve the stellar.toml file and check the signing key needed for the SEP-10 handshake.

In this page, we will cover the technical aspects of the SDP-Wallet integration, including how to add a Wallet in the SDP database, how to validate and support the registration links using mobile app's deep linking, how to start the user registration flow in the wallet using SEP-24, and a recommended approach for handling deferred deep linking.

Adding a Wallet to an SDP

The default list of SDP wallets depends on which network is being used (testnet or pubnet). The network is passed as an environment variable and then the list of wallets can be seeded appropriately on SDP startup through the CLI command ./stellar-disbursement-platform db setup-for-network, according with a hardcoded list of known wallets. Alternatively, wallets can be inserted directly into the SDP database through a SQL command. Both methods require adding the wallet name, homepage, SEP-10 client domain, and deep link schema.

To insert it directly into the database, update your values and run the following Postgres query. Make sure to check your database and namespace first.

INSERT INTO wallets (name, homepage, deep_link_schema, sep_10_client_domain)
VALUES ('Vibrant Assist', 'https://vibrantapp.com', 'https://vibrantapp.com/sdp', 'api.vibrantapp.com');

To configure a wallet through the code, add it to the testnet or pubnet section of DefaultWalletsNetworkMap. This will be used when you execute the ./stellar-disbursement-platform db setup-for-network CLI command, which updates the SDP database and makes the wallet available for new disbursements. Add your new wallet following the same format already present in the code.

var DefaultWalletsNetworkMap = WalletsNetworkMapType{
utils.PubnetNetworkType: {
{
Name: "Vibrant Assist",
Homepage: "https://vibrantapp.com/assist",
DeepLinkSchema: "https://vibrantapp.com/sdp",
SEP10ClientDomain: "api.vibrantapp.com",
},
},
utils.TestnetNetworkType: {
{
Name: "Vibrant Assist",
Homepage: "https://vibrantapp.com",
DeepLinkSchema: "https://vibrantapp.com/sdp-dev",
SEP10ClientDomain: "api-dev.vibrantapp.com",
},
{
Name: "Demo Wallet",
Homepage: "https://demo-wallet.stellar.org",
DeepLinkSchema: "https://demo-wallet.stellar.org",
SEP10ClientDomain: "demo-wallet-server.stellar.org",
},
},
}

Note: please make sure to update the appropriate configuration on the Anchor Platform side, according with the Anchor Platform Integration Points guide.

Recipient Registration Experience

The recipient registration experience is paramount to make this application smooth and easy to use. this requires the wallet to support deferred deep linking, which will be discussed in a later section. A good description of the registration experience is as follows:

  1. The recipient receives an SMS message notifying them they have a payment waiting from the organization and prompts them to click a deep link to open or install&open a wallet application

  2. When the recipient opens the wallet app, the wallet immediately onboards the recipient, creates a Stellar account and trustline for the desired asset, initiates a SEP-24 deposit transaction with the SDP, and opens the SDP's registration webpage as an overlay screen/iframe inside the app.

  3. The user confirms their phone number and date of birth directly with the SDP, without sharing any data with the wallet, and after the registration finishes, the user is sent back to the wallet application. Here are the screens demonstrating these steps:

    Registration Flow

  4. The user receives the payment within seconds

Once the user has installed the wallet application, the wallet should be able to interpret a deep link that follows the format registered in the SDP in order to kick off the Wallet Registration Procedure. The deep link format supported by the SDP follows this format:

https://<host-with-optional-path>?asset=<asset>&domain=<domain>&name=<name>&signature=<signature>
  • asset: the Stellar asset
  • domain: the domain hosting the SDP's stellar.toml file
  • name: the name of the organization sending payments
  • signature: a signature from the SDP's SEP-10 signing key

Note that the deep link is specific to each SDP, payer org, and asset. It is not specific per individual receiver. There is no risk in sharing the link with receivers who are part of the same disbursement. The link will be the same for multiple receivers and they will prove their identity as part of the SEP-24 deposit flow.

Below is an example of a registration link (signed)

https://vibrantapp.com/sdp-dev?asset=USDC-GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5&domain=ap-stellar-disbursement-platform-backend-dev.stellar.org&name=Stellar+Test&signature=fea6c5e805a29b903835bea2f6c60069113effdf1c5cb448d4948573c65557b1d667bcd176c24a94ed9d54a1829317c74f39319076511512a3e697b4b746ae0a

In this example, the host is https://vibrantapp.com/sdp-dev and the signature is the result of signing the below (unsigned) url using the SEP-10 signing key SBUSPEKAZKLZSWHRSJ2HWDZUK6I3IVDUWA7JJZSGBLZ2WZIUJI7FPNB5, with the public key being GBFDUUZ5ZYC6RAPOQLM7IYXLFHYTMCYXBGM7NIC4EE2MWOSGIYCOSN5F:

https://vibrantapp.com/sdp-dev?asset=USDC-GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5&domain=ap-stellar-disbursement-platform-backend-dev.stellar.org&name=Stellar+Test

In this example, the signature is fea6c5e805a29b903835bea2f6c60069113effdf1c5cb448d4948573c65557b1d667bcd176c24a94ed9d54a1829317c74f39319076511512a3e697b4b746ae0a.

Below is a JavaScript snippet demonstrating how to verify the signature:

#!/usr/bin/env node

const { Keypair } = require("stellar-sdk");

// The SDP's stellar.toml SIGNING_KEY
//
// For security, this should ideally be fetched from
// https://<domain>/.well-known/stellar.toml on demand
const keypair = Keypair.fromPublicKey(
"GBFDUUZ5ZYC6RAPOQLM7IYXLFHYTMCYXBGM7NIC4EE2MWOSGIYCOSN5F",
);
console.log("public key:", keypair.publicKey());

let url =
"https://vibrantapp.com/sdp-dev?asset=USDC-GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5&domain=ap-stellar-disbursement-platform-backend-dev.stellar.org&name=Stellar%20Test";
let signature =
"fea6c5e805a29b903835bea2f6c60069113effdf1c5cb448d4948573c65557b1d667bcd176c24a94ed9d54a1829317c74f39319076511512a3e697b4b746ae0a";

console.log(
"verified:",
keypair.verify(
Buffer.from(url.toString(), "utf8"),
Buffer.from(signature, "hex"),
),
);

Wallet Registration Procedure

When opening registration deep link, these are the steps the wallet should follow in order to enforce the security and privacy measures expected in this flow, and to allow the user to input their information directly with the SDP:

  1. 🚨 Confirm that the domain of the deep link is on the wallet's allowlist. This is crucial for authenticating from a trusted wallet.🚨
  2. Fetch the SDP's toml file at {domain}/.well-known/stellar.toml and confirm the SIGNING_KEY variable is populated.
  3. Verify that the registration link signature was made using SIGNING_KEY similar to the keypairPk.verify(...) function in the snippet above, and that the signature is valid with the content of the link.
  4. Check the asset from the link and confirm that the recipient user has a trustline for that asset. Create one if it doesn't exist.
  5. (Optional) Use the name from the link to update the wallet user interface.
  6. Initiate the SEP-24 deposit flow with that asset using the TRANSFER_SERVER_SEP0024 value from the SDP's toml file.
    • This includes using SEP-10 to authenticate the user with the SDP's server and implementing the client_domain check, as detailed in the SEP-10 spec.
  7. Launch the deposit flow interactive in-app browser within your mobile app, following the instructions in the SEP-24 spec.
    • ATTENTION: the wallet should not, in any circumstances, scrape or attempt to scrape the content from the in-app browser for the recipient's information.
    • NOTE: it's highly recommended to use an in-app browser rather than a webview.
  8. 🎉 Congratulations! The recipient user can now fill out the forms in the in-app browser and register to receive their payment 🎉.

Additionally, the wallet should save the link and/or link attributes and associate it with the individual receiving user for these reasons:

  1. This is how the wallet will know that the user is associated with a certain org or SDP.
  2. Saving the data is useful for reporting and troubleshooting, especially if the wallet needs to justify the source of funds for regulatory or tax purposes.
  3. If the payer org wants to pay any cashout fees charged by the wallet or offramp, the wallet will need to know which users and transactions should be invoiced upstream.

Most likely, the intended recipient will not have the necessary wallet application installed on their device. For this reason, wallets should support the concept of deferred deep linking, which enables the following flow:

  1. The recipient's initial action of clicking the deep link should redirect them to the appropriate app store to download the wallet application.
  2. After installing and opening the application, the recipient should be rerouted to the wallet's typical onboarding flow.
  3. Once the user has successfully onboarded, the wallet should use the information included in the deep link to kick off the Wallet Registration Procedure.

Deferred deep linking is a feature commonly supported by numerous mobile deep linking solutions, there are third-party services that can be used to implement this functionality, such as Singular, Branch, AppsFlyer, Adjust, and others. Here is a blog post with more information on how to implement deferred deep linking.

The SDP supports a basic link format, such as https://<host-with-optional-path>. If your wallet's deep linking system needs a more complex structure, you'll have to manage this with a web application. This application should be owned by the wallet provider, and it should be able to receive the deep link, interpret it, and direct the user to the correct location.