This page guides you through integrating the Superlink SDK with your Android application.

Prerequisites

Before you begin, ensure you have:

  • Completed the Superlink Partner Onboarding: You must be a Superlink partner to use our SDK. If you aren’t onboarded yet, please reach out to us.
  • Received a Partner ID: You must have a Partner ID to initialize the marketplace modal. You will receive a Partner ID when you onboard as a partner.
  • An Android Project: You must have an existing Android project to integrate the Android SDK.

Add the SDK to your project

Add the following to your project’s settings.gradle file:

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        ...
        mavenCentral()
    }
}

or build.gradle file:

allprojects {
    repositories {
        ...
        mavenCentral()
    }
}

Then add the following to your app build.gradle(.kts) (or use the gradle version catalog libs.versions.toml file):

Using the SDK

SuperlinkFragment

Using the SDK requires connecting your app’s user interface to the SuperlinkFragment Fragment subclass that is part of the Superlink SDK. To do this you must include the Superlink NavGraph into your application’s NavGraph.

Here’s what your NavGraph may look like:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/app_flow"
    app:startDestination="@id/myAppStartFragment">

    <include
        android:id="@+id/superlink"
        app:graph="@navigation/superlink" />

    <fragment
        android:id="@+id/myAppStartFragment"
        android:name="me.superlink.exampleapp.MyAppStartFragment"
        android:label="fragment_myAppStart">

        <action
            android:id="@+id/action_myAppStartFragment_to_superlink"
            app:destination="@id/superlink" >
            <argument
                android:name="partnerId"
                app:argType="string" />
            <argument
                android:name="userInfo"
                app:argType="me.superlink.sdk.data.UserInfo" />
        </action>

    </fragment>
</navigation>

Then to initialize the SDK you have to navigate to the included Superlink NavGraph destination using a navigation action, passing through the required arguments:

  • partnerId, a value of argType string, and
  • userInfo value of argType me.superlink.sdk.data.UserInfo defined as:
data class UserInfo(
    val wallets: List<Wallet>, 
    val externalUserId: String, 
    val email: String? = null, 
    val fullName:String? = null
) : Parcelable

and Wallet is defined as:

data class Wallet(
    val address: String, 
    val coin: String
) : Parcelable

You may perform this navigation from your application’s (Activity, Fragment or Jetpack Compose) user interface by invoking the navigation action defined in the NavGraph above with id action_myAppStartFragment_to_superlink, like so:

...
val action = MyAppStartFragmentDirections.actionMyAppStartFragmentToSuperlink(
    partnerId = "<someStringRepresentingAPartnerId>",
    userInfo = UserInfo(
        listOf(
            Wallet(
                "<user-wallet-address>", // e.g. "0xbDA07FBc7b184Ac0561DdB67f355b1Bc5a9E4428"
                "<coin-type-of-wallet>" // e.g. "ETH"
            )
        ),
        externalUserId = "<user-identifier>" // e.g. "12345"
    )
)

findNavController().navigate(action)

The above navigation operation will display a web page inside of a web view component embedded in the Superlink Fragment just navigated to.

The rest of the Superlink SDK APIs are then available via the SuperlinkViewModel class which subclasses the Android framework ViewModel class and provides access to data and operations from the Superlink SDK.

SuperlinkViewModel

In your Fragment above, you will need to instantiate the SuperlinkViewModel class as follows:

val superlinkViewModel = activityViewModels<SuperlinkViewModel>()

You may also use any other mechanisms for instantiating and scoping the SuperlinkViewModel as required by your app’s design.

Android Studio should auto-import the SuperlinkViewModel class and other Superlink classes, otherwise remember to manually import them:

import me.superlink.sdk.SuperlinkFragment
import me.superlink.sdk.SuperlinkViewModel
import me.superlink.sdk.data.UserInfo
import me.superlink.sdk.data.Wallet

The following properties and methods of the SuperlinkViewModel comprise the rest of the APIs the SDK offers.

transactionUrl: SharedFlow<String>

Use the SuperlinkViewModel class to handle purchasing a domain. You do this by observing an instance’s transactionUrl SharedFlow property, collecting the value it emits, performing your custom operation with it and then completing the transaction by calling the completeTransaction method on the instance.

The value will only be emitted when the user has selected crypto currency as their payment method. No value will be emitted for a fiat purchases.

The emitted value represents the transaction to be completed. It contains the recipient address, the coin type and the amount to be sent. The client application is expected to parse the URL and perform the transaction, before calling the completeTransaction method to notify the SDK that the transaction has been completed. Once completed, the the SDK will show a minting screen where the user waits for the transaction to be confirmed, before receiving their domain.

Here’s an example of observing the property inside a Fragment:

...
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    ...
    lifecycleScope.launch {
        // We use CREATED here because we want to be able to receive this data in the previous fragment but not leak 
        repeatOnLifecycle(Lifecycle.State.CREATED) {
            superlinkViewModel.transactionUrl.collect {
                Log.d("ExampleApp", "Transaction URL: $it")

                // This is just an example. This can be replaced with any custom UI, including using a different fragment since the view model is shared using the activity
                AlertDialog.Builder(requireContext())
                    .setTitle("Transaction URL").setMessage(it)
                    .setPositiveButton("OK") { _, _ -> 
                        // Do something with the collected value...

                        // ... And then notify the SDK you're done
                        superlinkViewModel.completeTransaction(transactionResult) 
                    }
                    .setNegativeButton("No") { _, _ -> }
                    .show()
            }
        }
    }

    ...
}
...

Here is an example of the value emitted by the transactionUrl property:

ethereum:0x965933D5C73ef443f3a2E4B370c3b6C964fc76eC?value=1.3062319352247146e17

Parsing the above yields:

  • coin type: ethereum
  • amount: 1.3062319352247146e17
  • recipient: 0x965933D5C73ef443f3a2E4B370c3b6C964fc76eC

completeTransaction(transactionID: String)

Like mentioned in the transactionUrl: SharedFlow<String> section above the completeTransaction() method allows your app to handover the transaction identifier back to the Superlink SDK. This will notify the SDK that the transaction has been completed and that the user can proceed to the minting screen.

transactionID: SharedFlow<String>

messageToSign: SharedFlow<String>

The Superlink SDK uses this property to provide a transaction that requires performing a digital signing operation by your application. Quite like the transactionUrl: SharedFlow<String> property, you observe this property and grab the emitted value for digital signing in your own application process.

The message will be emitted when the user claims a free username. The client application will be required to prompt the user to sign the message. Once the user signs the message, and the completeMessageSigning function is executed, the signed wessage will be sent back to the SDK which in turn sends it to the Superlink backend for verification. When the signed message is validated the user is given a free username.

Here’s an example:


override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    ...
    lifecycleScope.launch {
        repeatOnLifecycle(Lifecycle.State.CREATED) {
            superLinkViewModel.messageToSign.collect {
                Log.d("ExampleApp", "messageToSign: $it")

                // Grab the messageToSign and trigger a process to sign it...
                AlertDialog.Builder(requireContext()).setTitle("Sign This Message?")
                    .setMessage(it)
                    .setPositiveButton("Yes") { _, _ ->
                        // Initiate message signing ....
                        val messageSigned = it

                        // Now, pass through the signed message to the SDK
                        superLinkViewModel.completeMessageSigning(it, messageSigned)
                    }
                    .setNegativeButton("No") { _, _ -> }
                    .show()
            }
        }
    }
    ...
}

completeMessageSigning(originalMessage: String, signedMessage: String)

Already mentioned in messageToSign: SharedFlow<String> above, the completeMessageSigning(...) passes through to the SDK:

  • originalMessage: to identify the transaction that has been signed;
  • signedMessage: the digital signature

closeReason: SharedFlow<String>

The SDK closes the web view displaying the Superlink web content when a transaction is complete or when a transaction is signed. The closeReason property simply provides a success or empty string value to inform your application that the SDK has shutdown the web view. Like the other properties already mentioned, you’d have to observe it and handle changes to it accordingly, most likely to navigate back from the SuperlinkFragment and back to your app’s previous view.

Here’s how you can do this:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    ...
    lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.CREATED) {
                superLinkViewModel.closeReason.collect {
                    Log.d("ExampleApp", "closeReason: $it")

                    if (it == "success") {
                        findNavController().navigateUp()

                        val action = PurchaseFragmentDirections.actionGlobalPurchaseFragment()
                        findNavController().navigate(action)
                    } else {
                        findNavController().navigateUp()
                    }
                }
            }
        }
    ...
}

Custom view while SDK is loading

By including a layout/superlink_loading_view.xml file in your project’s layout resource directory, you can customize the loading screen that the Superlink SDK displays when loading the web content in the web view. Otherwise, Superlink uses a default view.

Here’s an example:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp"
        android:text="Getting your transaction ready"
        app:layout_constraintBottom_toTopOf="@+id/progress"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <com.google.android.material.progressindicator.CircularProgressIndicator
        android:id="@+id/progress"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:indeterminate="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>