Provides a solution for easy implementation of the custodial Gari Wallet in your products. Web3Auth is used as a layer for saving wallet credentials. Check Web3Auth documentation to get more information (https://web3auth.io/docs/)
- create wallet
- get wallet state (activated, not registered yet)
- requesting airdrop
- transfer Gari token
- Android API version 24 or newer is required.
Open your app module gradle.build file, and add the gari dependency:
dependencies {
...
implementation 'io.github.gari-network:gari-wallet:0.2'
...
}
Open your app's AndroidManifest.xml
file and add the following permission:
<uses-permission android:name="android.permission.INTERNET" />
Open your gradle.build file for your main application module - override manifest variables $authRedirect. This URL will be used as a deep link scheme for Web3Auth redirects.
You should add it to the whitelist during configuring the Web3Auth dashboard. Read the documentation to get more information - https://web3auth.io/docs/sdk/android/#configure-a-plug-n-play-project
All Logic for handling deep link redirects has been already handled by Gari Wallet SDK, you just need to declare manifest variable in your Gradle scripts.
android {
namespace 'io.gari.sample'
compileSdk appConfig.compileSdk
defaultConfig {
...
manifestPlaceholders = [authRedirect: "io.coin.gari"]
...
}
- Extend your Application class from GariApp
class DemoApplication : GariApp() {
override fun onCreate() {
super.onCreate()
...
}
}
Set web3auth config:
- web3AuthClientId: client id from web3auth dashboard
- redirectUrl: consist of 2 parts (package name + path, e.g. - io.coin.gari://auth), it should be added to the white list in the web3auth dashboard, and scheme of the URL should be added as manifestPlaceholder (check [here] (#manifest-placeholder))
- clientId: - your personal gari client id
- verifierIdField: - field key which identifies the user in your JWT token
- verifier: - verifier name which is registered in the web3auth dashboard
- verifierTitle: - title for web3auth web page
- verifierDomain: - a domain where your API service deployed for token verification
- network: - type of network for web3auth configuration (check documentation of web3auth https://web3auth.io/docs/sdk/android/initialize#web3authoptions)
class DemoApplication : GariApp() {
override fun onCreate() {
super.onCreate()
val web3AuthConfig = Web3AuthConfig(
web3AuthClientId = "",
redirectUrl = "io.coin.gari://auth",
verifierIdField = "uid",
verifier = "your-verifier-name",
verifierTitle = "Gari Wallet Demo",
verifierDomain = "https://demo-gari-sdk.vercel.app",
network = Web3Network.TESTNET
)
Gari.initialize(
clientId = "d8817deb-dceb-40a4-a890-21f0286c8fba",
web3AuthConfig = web3AuthConfig
)
}
}
- Start using Gari..
Gari wallet SDK is completely friendly with coroutines API. It should be easy to implement into every project with MVVM architecture.
Here is an example how you can retrieve the wallet state by the user's token:
class WalletDetailsViewModel : ViewModel() {
val walletState = MutableLiveData<GariWalletState>()
init {
loadWalletDetails()
}
private fun loadWalletDetails() {
viewModelScope.launch {
val state = Gari.getWalletState(web3AuthToken)
walletState.postValue(state)
}
}
}
Design of GariWalletState class allows you to properly handle every situation on your UI:
sealed class GariWalletState {
class Activated(val pubKey: String, val balance: String) : GariWalletState()
object NotExist : GariWalletState()
class Error(val error: Throwable?) : GariWalletState()
}
The token of the user should be refreshed before calling Gari.createWallet(). This limitation is coming from the Web3Auth SDK.
What is WalletKeyManager and where you can get it - check the "Key Management" documentation below on the page
class WalletDetailsViewModel : ViewModel() {
fun registerWallet(keyManager: WalletKeyManager, userJwtToken : String) {
viewModelScope.launch {
val walletResult = Gari.createWallet(
keyManager = keyManager,
token = userJwtToken
)
}
}
}
The token of the user should be refreshed before calling the function Gari.transferGariToken(). This limitation is coming from Web3Auth SDK.
Every transaction consists of 2 steps:
- Create signed transaction through Gari Wallet Sdk
- Send transaction into your backend for future processing
For getting a signed transaction you can follow this example:
class WalletDetailsViewModel : ViewModel() {
fun sendTransaction(walletKeyManager: WalletKeyManager) {
val receiverPublicKey = ""
val transactionAmount = "1" // 1 GARI
val user userJwtToken = ""
val amount = transactionAmount.toBigDecimalOrNull()
?.toLamports()
?.toString()
?: return
viewModelScope.launch {
Gari.transferGariToken(
token = userJwtToken,
keyManager = walletKeyManager,
receiverPublicKey = receiverPublicKey,
transactionAmount = amount
).onSuccess { signedTransaction ->
/* send transaction into your backend for future processing */
}.onFailure {
/* handle error on UI */
}
}
}
}
Airdrop operation requires a wallet private key - from which Gari tokens will be transferred into the user account.
class AirdropViewModel : ViewModel() {
fun requestAirdrop() {
val airdropAmount = "1" // 1 Gari
val airdropSponsor = "" // private key of wallet from which amount will be transferred (encoded in HEX)
val userJwtToken = ""
val publicKey = "" // user who will be credited with Gari tokens
viewModelScope.launch {
Gari.getAirDrop(
token = userJwtToken,
amount = airdropAmount,
destinationPublicKey = publicKey,
sponsorPrivateKey = airdropSponsor.decodeHex()
).onSuccess { signature ->
// signature - it's transaction signature
}.onFailure {
// handle error on UI
}
}
}
}
For operations which are a required wallet private key (like transactions), you have instantiated WalletKeyManager, which is part of Gari Wallet SDK
object Gari {
...
fun provideWalletKeyManager(resultCaller: ActivityResultCaller): WalletKeyManager {
return WalletKeyManager(resultCaller)
}
...
}
This action depends on Activity Result APIs - so you have to create it before .onCreate() lifecycle function of your Activity or Fragment
class WalletDetailsActivity : AppCompatActivity() {
private val walletKeyManager = Gari.provideWalletKeyManager(this)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
}
}