Not everyone has access to a smartphone or internet, which leaves them excluded from digital finance and emerging innovations. Further, the research we have carried out regarding CBDC's suggests that majority of central banks will adopt a hybrid model where they issue the retail CBDC but partner with service providers to manage the day to day operations i.e. manage retail user accounts/wallets. These service providers (which include retail banks and fintechs) will cater to various segments of the market. Given these considerations, we realise the need for a service provider, whose focus is on the unbanked segment of the market i.e. the segment without smartphones or internet. Hence the idea of the Mandla Money CBDC SMS Wallet - a low-tech SMS wallet for retail users that supports CBDCs and stablecoins that does not require a smartphone or an internet connection . Mandla is a name of African origin which means power, we believe our wallet gives power to the people. Mandla Money - Power to the people!

What it does

Users can register on the SMS wallet by sending a "Hello Mandla" SMS to the wallet number. The Mandla servers will check if the user is registered by querying using their cell number and if not registered, will generate a unique wallet ID (we call this the Mandla ID) and map this to the users cellphone number. Once registered, a user can then send digital assets to another user (e.g. send#asset#REPLACECELLNUMBER#value e.g. sending USD10 from one Mandla Money user to another would be send#usd#REPLACECELLNUMBER#10). In order to send assets from an external wallet (one that is not part of the Mandla Money ecosystem), one would simply need to send the supported asset to a Mandla Money user xaddress (i.e. the Mandla custody address combined with the user's Mandla ID which is an XRPL memo under the hood).

This wallet has been tested with XRP (native asset), FOO (issued asset from XRPL transaction sender), XAGO.ZAR (a ZAR stablecoin issued by in South Africa) and USD stablecoin (

Behind the scenes, there is configuration that specifies supported assets, and so this is how onboarding a CBDC would occur. It would be added to the supported assets, a trust line set up between the CBDC issuer and the Mandla Money custody account and

How we built it

Mandla CBDC wallet is built using a Django backend, xrpl-py SDK, Postgres DB and Twilio SDK for sending SMS's over the internet. Using Twilio, we can send, receive and parse SMS's from our Django backend server.

In order to detect new transactions, we implemented a scheduled task that calls a URL that polls the XRP ledger for new transactions using our custody address (, when new transactions are detected, they are imported into the application which trigger the relevant allocation based on the specified user tag/memo.

Further, in order to support issued assets, we had to create a trust line between our custody address and the relevant issuer address i.e. rw4WrHbV63xEYGMkxAyuzpJoSXjtbGysvS for the FOO asset -, r3YeuAYfvnKqaaA5kK6Gaf6dKV3GHyuwds for the USD asset and another to for the ZAR asset). Specifically, for the USD asset, we had to issue this for demonstration purposes.

The demo wallet is deployed on Heroku and can be accessed via SMS (send a "Hello Mandla" SMS to +27600178563

Challenges we ran into

Setting the hot address AccountSet transaction (i.e. the Mandla custody address), we ran into the following error. xrpl.asyncio.transaction.reliable_submission.XRPLReliableSubmissionException: Transaction failed, tecOWNERS: Non-zero owner count. We checked for the meaning of this error on and found the following - tecOWNERS 132 The transaction requires that account sending it has a nonzero "owners count", so the transaction cannot succeed. For example, an account cannot enable the lsfRequireAuth flag if it has any trust lines or available offers. We then removed the AccountSetFlag.ASF_REQUIRE_AUTH on the AccountSet transaction since the Mandla custody account has existing trustlines (e.g. to for the ZAR asset). We found this documentation also useful Transaction failed, tecOWNERS: Non-zero owner count.

Accomplishments that we're proud of

We managed to issue a USD stablecoin and integrate it our wallet with ease. We have also started making improvements to our code to make it more robust e.g. use of the phonenumbers module in Django to parse the SMS numbers efficiently based on region etc.

What we learned

We started by exploring the use of the XRPL DEX in order to trade XRP for USD to load in our wallet. We tried to use this account rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B but it seems in the testnet it does not have any USD asset (i.e. whilst on mainnet it does ( We then checked the xrpl-py issues to see if there is a testnet faucet available for other assets like USD and stumbled upon this issue This inspired us to write a script to issue our own USD asset and send to our wallet so we can demonstrate how to support multiple CBDC's or stablecoins. We learnt how to check the DEX for Offers and how to issue stablecoins on XRPL.

What's next for CBDC SMS Wallet

We need to build a Stablecoin/CBDC dashboard to allow onboarding of new assets via a front end and not via scripts. We also need an Account Management dashboard to allow an admin to view individual user accounts, transactions and balances (akin to a bank). We also need to integrate with mainnet XRP DEX for USDC redemptions and lastly configure our custody wallets as per recommendation i.e. Cold wallet, standby wallet and hot wallet.

Share this project: