НОВОЕ: Helius приобретает Light Protocol
Создайте мобильное приложение для минтинга cNFT менее чем за 5 минут
Блог/Разработка

Создайте мобильное приложение для минтинга cNFT менее чем за 5 минут

Инженер по работе с разработчикамиAnam Ansari в XAnam Ansari в LinkedIn
Чтение: 5 мин

Что вас ждет

В этом руководстве показано, как создать Android-приложение для минтинга NFT (невзаимозаменяемых токенов). Оно позволит пользователям легко снимать изображения и минтить сжатые NFT в Solana. Для этого мы воспользуемся Helius Mint API. Этот API ускоряет минтинг сжатых NFT и сокращает объем шаблонного кода, экономя время на разработку и планирование. Мы напишем Android-приложение на Kotlin с использованием Jetpack Compose.

Что такое сжатые NFT?

Сжатые NFT (cNFT) используют сжатие состояния и параллельные деревья Меркла, чтобы снизить затраты на хранение. Сжатые NFT обходятся в 2 400–24 000 раз дешевле несжатых аналогов, сохраняя при этом идентичную структуру.

Предварительные требования

Перед началом работы вам потребуются базовые знания о разработке Android-приложений на Kotlin и знакомство с Solana.

Инструменты

  • Android Studio: Giraffe | Версия 2022.3.1
  • Эмулятор или мобильное устройство: потребуется для тестирования приложения. Убедитесь, что установлено приложение кошелька, совместимого с MWA (рекомендуется Solfare).

Ключ API

Для работы с Helius Mint API потребуется ключ API. Вот как его получить:

  1. Откройте портал Helius для разработчиков.
  2. Создайте учетную запись с помощью кошелька Solana либо аккаунта Google или GitHub.
  3. После входа следуйте подсказкам, чтобы сгенерировать ключ API.
  4. Храните этот ключ в безопасном месте: он потребуется для вызовов API на протяжении всего руководства.

Создание приложения

Шаг 1. Настройка проекта

Мы подготовили для этого проекта стартовую кодовую базу. 

Чтобы начать работу, выполните следующие действия:

  1. Откройте стартовый набор на GitHub.
  2. Создайте форк репозитория и клонируйте его в локальную среду.

Загрузив код в локальную среду, выполните следующие действия:

  1. Откройте проект в Android Studio.
  2. Дождитесь завершения сборки Gradle.
  3. Запустите код.

Изучите стартовое приложение и ознакомьтесь с его возможностями. Обратите внимание на встроенную кнопку подключения кошелька. Она позволяет подключаться к любым приложениям кошельков, совместимым с Mobile Wallet Adapter (MWA). Mobile Wallet Adapter (MWA) — это спецификация протокола для подключения мобильных dApp к мобильным приложениям кошельков. Она обеспечивает обмен данными для транзакций Solana и подписания сообщений. Mobile Wallet Adapter поддерживает эти кошельки. Кроме того, в приложении есть кнопка «Сделать снимок», которая пока позволяет только снимать изображения.

Чтобы безопасно хранить ключ Helius API в кодовой базе, откройте файл local.properties и добавьте в него ключ API. Этот файл предназначен специально для конфиденциальной информации и игнорируется Git, поэтому ваш ключ API останется в безопасности.

api_key=<your-api-key>

Теперь реализуем логику минтинга снятого изображения в виде сжатого NFT (cNFT).

Шаг 2. Логика минтинга

Наша цель — связать кнопку «Сделать снимок» с камерой. Благодаря этому пользователи смогут снимать изображения и минтить их как NFT. Мы предоставили стартовый код для открытия камеры и съемки изображений. Теперь создадим функцию для управления процессом минтинга.‍

Mint API от Helius

Этот метод минтит сжатый NFT. После запуска он приостановит выполнение до подтверждения транзакции. При пиковой нагрузке на сеть это может занять до 60 секунд. Подробнее см. в документации.

Сначала откройте java/com/example/hmint/MainViewModel.kt и создайте функцию mintCNft в классе MainViewModel:

Код
@HiltViewModel
class MainViewModel @Inject constructor(
    private val walletAdapter: MobileWalletAdapter,
    private val walletConnectionUseCase: WalletConnectionUseCase,
) : ViewModel() {
    
    // ...

    fun mintCNft(imageUri: Uri, nftName: String, user: String) =
        viewModelScope.launch {
            _state.update {
                _state.value.copy(
                    isLoading = true,
                )
            }
        }

}

‍Внутри этой функции запустим корутину, которая будет обрабатывать логику минтинга. Сначала получим ключ API, определим необходимые переменные и requestBody. Позже вы сможете настроить requestBody и добавить дополнительные атрибуты и данные в соответствии со своими требованиями:

Код
withContext(viewModelScope.coroutineContext + Dispatchers.IO) {
    val apiKey = System.getProperty("api_key") ?: ""
    val url = URL("https://mainnet.helius-rpc.com/?api-key=$apiKey")
    val mediaType = "application/json".toMediaTypeOrNull()
    val requestBody = """
        {
            "jsonrpc": "2.0",
            "id": "helius-test",
            "method": "mintCompressedNft",
            "params": {
                "name": "$nftName",
                "symbol": "HM",
                "owner": "$user",
                "description": "This is a test cNFT minted by hMint app",
                "attributes": [
                    {
                        "trait_type": "hMint",
                        "value": "1"
                    }
                ],
                "imageUrl": "$imageUri",
                "sellerFeeBasisPoints": 6900
            }
        }
        ""${'"'}.trimIndent()
                                    
}

‍Затем сформируем запрос и инициализируем OkHttpClient:

Код
val body = requestBody.toRequestBody(mediaType)
val request = Request.Builder()
    .url(url)
    .post(body)
    .addHeader("accept", "application/json")
    .addHeader("content-type", "application/json")
    .build()
val client = OkHttpClient()

‍Перед вызовом клиента определим ответ с помощью класса данных. Создайте новый пакет с именем data, а внутри него — новый файл NFTResponse.kt. В нем определите структуру ответа, получаемого при вызове API.

Код
package com.example.hmint.data

data class NftMintResponse(
    val jsonrpc: String,
    val id: String,
    val result: MintResult
)

data class MintResult(
    val signature: String,
    val minted: Boolean,
    val assetId: String
)

‍Затем в классе MainViewModel дополните класс данных WalletViewState новым значением для mintResponse. Мы обновим его после получения ответа:

Код
data class WalletViewState(
    // ...
    val mintResponse: String = ""
)

‍Вернемся к функции mintCNft. С помощью клиента выполним запрос и обработаем возможные ошибки или полученный ответ. После получения ответа используем Gson, чтобы преобразовать данные в ранее созданный класс данных NFTMintResponse, а затем соответствующим образом обновим значение mintResponse:

Код
client.newCall(request).enqueue(object : Callback {
    override fun onFailure(call: Call, e: IOException) {
        // Handle failure
        e.printStackTrace()
        Log.d(TAG, "NFT Mint Failed")
        _state.update {
            _state.value.copy(
                isLoading = false,
                mintResponse = "Mint Failed"
            )
        }
    }

    override fun onResponse(call: Call, response: Response) {
        if (response.isSuccessful) {
            val responseBody = response.body?.string() ?: ""
            val gson = Gson()
            val nft = gson.fromJson(responseBody, NftMintResponse::class.java)
            Log.d(TAG, "NFT Mint Successful: $nft")
            _state.update {
                _state.value.copy(
                    isLoading = false,
                    mintResponse = "Minted Successfully"
                )
            }

        } else {
            // Handle non-successful response
            Log.d(TAG, "NFT Mint Failed: ${response.code}")
            _state.update {
                _state.value.copy(
                    isLoading = false,
                    mintResponse = "Minted Failed"
                )
            }
        }
    }
})

‍В UI нужно сообщить пользователю результат выполнения функции минтинга. Поэтому откройте java/com/example/hmint/composables/MintButton.kt с компонуемой функцией, которая содержит код UI и логику съемки изображений. В MintButton, где объявлен cameraLauncher, вызовите функцию mintCNft. Также добавьте код для отображения Toast после обновления mintResponse.

Код
@Composable
fun MintButton(
    mainViewModel: MainViewModel = hiltViewModel()
) {

    val cameraLauncher =
        rememberLauncherForActivityResult(ActivityResultContracts.TakePicture()) {
            // ...
            mainViewModel.mintCNft(uri, "hMint", viewState.userAddress)
        }

    
    viewState.mintResponse.let { message ->
        if(message.isNotEmpty()){
            Toast.makeText(LocalContext.current, message, Toast.LENGTH_SHORT).show()
        }
    }

    // ...
}

Шаг 3. Запуск приложения

‍Мы закончили писать код, поэтому теперь запустим приложение. Сначала подключите кошелек, затем сделайте снимок и наблюдайте, как приложение автоматически минтит для вас NFT.

Заключение

Готово! Вы успешно разработали Android-приложение, которое позволяет пользователям минтить сжатые NFT. Благодаря Helius Mint API минтинг cNFT стал проще, чем когда-либо: достаточно всего одного вызова.

Что дальше?

Приложение можно исследовать и улучшать дальше. Например, можно интегрировать DAS API. Digital Asset Standard (DAS) API — это спецификация и система с открытым исходным кодом, предоставляющая единый интерфейс для работы с цифровыми активами, включая токены и NFT. Она поддерживает разные типы активов: взаимозаменяемые токены, стандартные NFT и сжатые NFT.  С помощью API можно получить все созданные сжатые NFT и отобразить их в приложении, предоставив пользователям полный обзор их цифровых активов.

Полезные ресурсы

Чтобы углубить знания о разработке Android-приложений с Jetpack Compose, интеграции блокчейна Solana и работе с API, изучите следующие ресурсы:

Если вам нужна помощь или поддержка, свяжитесь с нами в Discord. Полная кодовая база доступна на GitHub.

‍

Подпишитесь на Helius

Следите за новостями разработки на Solana и получайте уведомления о наших публикациях

Увеличенное изображение