Using Native Accounts to Interact with Your User’s Assets | The Radix Blog | Radix DLT
YOU ARE: A front-end or Scrypto developer
YOU’RE BUILDING: Any application that needs to interact with with user accounts
THE PROBLEM TO SOLVE: How to interact with user accounts and assets as part of using your dApp, sending tokens to users, and more.
THE TOOL TO USE: The Radix Network’s native Account component, the Transaction Manifest, and the Radix Wallet
Perhaps the most important part of Web3 is that it enables true digital ownership – the ability of users to hold and control their own digital assets. To make those assets useful, dApps need to be able to interact with the accounts where users’ assets are held.
On Radix, accounts are not simply addresses as on most blockchains. Instead, they are components, and the Radix Network provides a special native Account blueprint that is used universally. This Account blueprint includes a variety of functionality, and in combination with an “Access Controller” component that implements multi-factor control and recovery logic it is sometimes called a “Smart Account”.
A separate article discusses the range of user features enabled by Smart Accounts. That article is highly recommended reading before continuing with this one. Given those features, developers of dApp front-ends and on-network Scrypto components need to understand how to interact with the Account component to be able to build rich applications around the use of assets.
On Radix, Accounts are containers for assets and so there are three essential actions of the native Account component that you will need to understand how to use when building your dApp to interact with user assets:
- Withdrawing Assets
- Depositing Assets
- Getting Proofs of Assets
Knowing how to use the methods offered by Account component to accomplish those actions will help you with a range of use cases, such as:
- Doing simple token transfers
- Conducting DeFi transactions
- Performing airdrops
- Manipulating assets with a server backend
- Providing and verifying user identity on-network
The Radix Tool for the Job
Any interaction with an Account requires building and submitting a transaction to the Radix Network that calls methods on the Account component.
The Radix developer docs include the full definition of the Account component’s method interface.
A separate article discusses how to construct transactions, and the specific way in which to construct them for the Radix Wallet, including use of Radix dApp Toolkit and Radix Engine Toolkit where appropriate.
The Recommended Use Pattern
We will focus on patterns of usage in interaction with Accounts owned by your users. See Additional Notes below for information on interacting with Accounts controlled directly by your system.
There are two ways for your dApp to interact with a user’s Account in transactions:
- Calling the Account via request to the user’s Radix Wallet app
- Calling the Account directly
These two ways have distinct purposes.
Calling an Account via request to the Radix Wallet app must be done whenever the user’s authorization is required to make the method call. Here your dApp is actually proposing (or “requesting”) a transaction to the user’s Radix Wallet. Typically this is done by your dApp’s front-end using the wallet request features of Radix dApp Toolkit.
The user will have the opportunity to review the transaction in their Radix Wallet, and the wallet will provide the required signatures to make the desired calls. Essentially they are the ones making the calls to their own Account; your dApp has simply constructed the transaction to assist them with doing what they want to do with your dApp, using their own Accounts and assets.
This is the typical approach for DeFi transactions, and is nearly always the approach to use whenever you have a user that is directly using your own application front-end. It provides the best user experience, and allows access to Account methods that are only callable by the Account’s owner. Even in situations where your dApp wishes to simply send tokens to a user, it is often preferable to propose a transaction in which the user claims those tokens from a component.
Calling an Account directly is necessary when you cannot (or do not wish to) directly connect to the user’s Radix Wallet. This will typically be done using your own server backend system, and you may construct and submit the transaction using Radix Engine Toolkit and the Gateway SDK.
This is essentially limited to one purpose: depositing assets directly to a user’s account. This might be an exchange sending tokens to a user from a shared hot wallet, conducting an airdrop to many accounts, or directly transferring tokens to a user in special situations where the “claim” model is unworkable.
It is extremely common for a dApp to propose transactions in which assets are withdrawn from a user’s account for use. For example, a transaction to perform a DEX swap would begin by withdrawing some tokens from an account before passing those tokens to the swap method of the DEX component.
The Account component provides two withdrawal methods: withdraw (for fungible tokens) and withdraw_non_fungibles (for non-fungible tokens). Both are only callable by the Account’s owner, and so can only be called via a transaction request to the user’s wallet app.
When constructing a transaction manifest to propose to the user’s wallet, you should simply include the withdraw call. The Radix Wallet will automatically determine the signature(s) required to make that call and make sure they are included.
Because many transactions involve depositing of assets to third party accounts, the Account offers two sets of depositing methods – one set for the owner, and one set for third parties.
The deposit and deposit_batch methods are, like the withdraw methods, only callable by the Account’s owner. Like withdraw, they should be used whenever proposing a transaction to the user’s wallet where they can provide the authority to use them. The “batch” version is simply for deposits of multiple kinds of assets at once.
A few other methods are provided that start with try_deposit. These are specifically intended to be called by third parties – not the owner – and they do not require any auth to call. However, they are subject to some third party deposit preferences that the owner can set. For a variety of reasons, a given deposit may violate those preferences and be rejected. The …or_refund and …or_abort variations of try_deposit determine how to handle that rejection – either by returning the bucket back to the caller/worktop or simply aborting the transaction.
For example, a transaction conducting an airdrop would likely want to use try_deposit_or_refund and then, as a last line of the transaction, deposit all assets on the worktop back to an account controlled by the sender. That final “sweeping up” will pick up any assets which were returned by accounts whose rules disallowed the attempted airdrop.
Because the try_deposit methods are subject to the user’s deposit preferences, it should only be used in specific circumstances. It’s highly preferable, wherever possible, to conduct deposits using a transaction proposed to the user’s wallet that can use the deposit or deposit_batch methods that alway succeed regardless of the asset. Even when you have a Scrypto component that wishes to send tokens to a user’s Account, it is preferable to not try_deposit to them directly. The preferred approach is to put those tokens into a vault and provide a front-end to propose a transaction to the user’s wallet to claim those tokens.
Getting Proofs of Assets
Your dApp’s components may be configured to require proof of a given asset (typically termed a “badge” in this case) in order to call some of its methods.
The Account provides a few create_proof methods to make this possible. Again, these methods are only callable by the Account’s owner, and so this can only be done in a transaction proposed to their wallet. As with withdraw and deposit, your dApp should simply include the create_proof call in the proposed transaction manifest and the Radix Wallet will automatically determine and provide the auth required.
What About Multi-factor?
The Account component includes special logic to allow configuration of multi-factor control and recovery. This includes use of a special Access Controller component that implements the multi-factor logic and is used in tandem with the Account. So, what does a dApp need to do to work with multi-factor Accounts paired with an Access Controller?
Fortunately the answer is nothing at all. When proposing transactions to the user’s wallet, your dApp can simply make the deposit/withdraw/create_proof calls it needs. If the Account in question requires use of an associated Access Controller or gathering of multiple signatures, the Radix Wallet will automatically handle it. It will add the required instructions to the transaction manifest, and gather all required signatures.
Essentially multi-factor is a completely user/wallet-managed set of features and your dApp never needs to think about it.
What About Locking Fees?
You might notice that the Account component also includes methods to lock fees to pay for transactions. What does a dApp need to do with those methods? Once again, the answer is nothing at all. The fee locking methods are reserved for use by the user’s wallet, which will automatically calculate the fees that must be locked and add the lock fee instruction to the transaction manifest according to user preferences.
All of the above describes interacting with Accounts owned by your users. It should be noted that your system itself may own Accounts. For example, an exchange may have custodial Accounts, or your dApp may have reserves of assets in algorithmically-controlled Accounts.
When your system is the Account owner, it of course has the rights to use the Account’s owner-only methods, as described above. You do not need to use the Radix Wallet to conduct these transactions because your system can construct, sign, and submit them to the network directly. In this case, your system will need to ensure it includes any required Access Controller calls (if you choose to use the Access Controller’s multi-factor features), makes the required fee locking call, and applies the correct signatures to authorize use of the Account.
- How Radix Multi-Factor Smart Accounts Work and What They Can Do
- Native Account Component specification
- Using Transaction Manifests to Give Wallet Users Confidence
- Radix dApp Toolkit documentation
- Radix Engine Toolkit documentation
- Gateway SDK documentation