Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: paybis integration #49

Merged
merged 5 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.3.1]:

* feature: Paybis integration of crypto on-ramp

## [0.3.0]:

* Feature: submit button on settings page
Expand Down
8 changes: 5 additions & 3 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ android {
applicationId "org.satochip.satodimeapp"
minSdk 24
targetSdk 34
versionCode 300
versionName "0.3.0"
versionCode 301
versionName "0.3.1"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
Expand All @@ -29,6 +29,8 @@ android {
buildConfigField "String", "API_KEY_BSCSCAN", "\"${properties.getProperty("API_KEY_BSCSCAN")}\""
buildConfigField "String", "API_KEY_RARIBLE", "\"${properties.getProperty("API_KEY_RARIBLE")}\""
buildConfigField "String", "API_KEY_COVALENT", "\"${properties.getProperty("API_KEY_COVALENT")}\""
buildConfigField "String", "API_KEY_PAYBIS_ID", "\"${properties.getProperty("API_KEY_PAYBIS_ID")}\""
buildConfigField "String", "API_KEY_PAYBIS_HMAC", "\"${properties.getProperty("API_KEY_PAYBIS_HMAC")}\""
}

buildTypes {
Expand Down Expand Up @@ -88,7 +90,7 @@ dependencies {
implementation files('libs/satochip-android-0.0.2.jar')
//implementation files('libs/javacryptotools-0.1.0.jar')
//implementation files('libs/javacryptotools-0.2.0.jar')
implementation files('libs/javacryptotools-0.3.0.jar')
implementation files('libs/javacryptotools-0.3.1.jar')

//satochip-android & satochip-lib related dependencies
implementation("org.bouncycastle:bcprov-jdk15on:1.70")
Expand Down
Binary file not shown.
15 changes: 14 additions & 1 deletion app/src/main/java/org/satochip/satodimeapp/Navigation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.pm.ActivityInfo
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalUriHandler
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
Expand Down Expand Up @@ -38,10 +41,16 @@ import org.satochip.satodimeapp.ui.components.AcceptOwnershipView
import org.satochip.satodimeapp.util.NavigationParam
import org.satochip.satodimeapp.util.SatodimePreferences
import org.satochip.satodimeapp.util.SatodimeScreen
import org.satochip.satodimeapp.util.apiKeys
import org.satochip.satodimeapp.viewmodels.SharedViewModel
import java.net.URLEncoder
import java.util.Base64
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec

private const val TAG = "Navigation"

@RequiresApi(Build.VERSION_CODES.O)
@SuppressLint("SourceLockedOrientationActivity")
@Composable
fun Navigation() {
Expand Down Expand Up @@ -160,7 +169,11 @@ fun Navigation() {
)
) {
val selectedVault = it.arguments?.getInt(NavigationParam.SelectedVault.name)!!
AddFundsView(navController, sharedViewModel, selectedVault)
AddFundsView(
navController,
sharedViewModel,
selectedVault,
)
}

// UNSEAL
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/org/satochip/satodimeapp/data/CardVault.kt
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ final class CardVault (val cardSlot: CardSlot, val context: Context) {
val coin: Coin = try {
if (nativeAsset.symbol == "ROP")
Coin.ETH
else if (nativeAsset.symbol == "MATIC") {
Coin.MATIC
else if (nativeAsset.symbol == "POL") {
Coin.POL
}
else
Coin.valueOf(nativeAsset.symbol.take(3)) //todo: clean?
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/org/satochip/satodimeapp/data/Coin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ enum class Coin(val label: String, val painterResourceId: Int) {
LTC("Litecoin", R.drawable.litecoin),
BCH("Bitcoin Cash", R.drawable.bitcoin_cash),
XCP("Counterparty", R.drawable.counterparty),
MATIC("Polygon", R.drawable.polygon),
POL("Polygon", R.drawable.polygon),
UNKNOWN("Unknown", R.drawable.top_left_logo)
}
74 changes: 64 additions & 10 deletions app/src/main/java/org/satochip/satodimeapp/ui/AddFundsView.kt
Original file line number Diff line number Diff line change
@@ -1,39 +1,93 @@
package org.satochip.satodimeapp.ui

import android.os.Build
import androidx.annotation.RequiresApi
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import androidx.navigation.compose.rememberNavController
import org.satochip.satodimeapp.R
import org.satochip.satodimeapp.data.CardVault
import org.satochip.satodimeapp.ui.components.DisplayDataView
import org.satochip.satodimeapp.ui.theme.SatodimeTheme
import org.satochip.satodimeapp.util.apiKeys
import org.satochip.satodimeapp.viewmodels.SharedViewModel
import java.net.URLEncoder
import java.util.Base64
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec

@Composable
fun AddFundsView(navController: NavController, sharedViewModel: SharedViewModel, selectedVault: Int) {
// val satodimeStore = SatodimeStore(LocalContext.current)
// val vaults = satodimeStore.vaultsFromDataStore.collectAsState(initial = emptyList()).value
//
// if(vaults.isEmpty() || vaults[selectedVault - 1] == null) return
// val vault = vaults[selectedVault - 1]!!

fun getAddressForPaybis(cardVault: CardVault): String {

// for BCH, remove prefix
if (cardVault.nativeAsset.symbol=="BCH"){
val address = cardVault.nativeAsset.address.removePrefix("bitcoincash:")
return address
}

return cardVault.nativeAsset.address
}

fun getCurrencyCodeForPaybis(cardVault: CardVault): String? {

// testnet not supported
if (cardVault.isTestnet){return null}
// xcp not supported
if (cardVault.nativeAsset.symbol=="XCP"){return null}

return cardVault.nativeAsset.symbol
}

@RequiresApi(Build.VERSION_CODES.O)
@Composable
fun AddFundsView(
navController: NavController,
sharedViewModel: SharedViewModel,
selectedVault: Int,
) {
val cardVaults = sharedViewModel.cardVaults
val cardVaultsSize = cardVaults?.size ?: 0
if(selectedVault>cardVaultsSize || cardVaults?.get(selectedVault - 1) == null) return
val cardVaultsSize = cardVaults.size
if(selectedVault>cardVaultsSize || cardVaults.get(selectedVault - 1) == null) return
val cardVault = cardVaults[selectedVault - 1]!!

// for crypto purchase using paybis
val depositAddress = getAddressForPaybis(cardVault= cardVault) //cardVault.nativeAsset.address
val currencyCodeTo = getCurrencyCodeForPaybis(cardVault= cardVault)
var paybisUrl: String? = null
if (currencyCodeTo != null) {
val apiKey = apiKeys["API_KEY_PAYBIS_ID"]
val hmacKey = apiKeys["API_KEY_PAYBIS_HMAC"]
val uri = "https://widget.paybis.com/"
val query = "?partnerId=$apiKey" +
"&cryptoAddress=$depositAddress" +
"&currencyCodeFrom=EUR" +
"&currencyCodeTo=$currencyCodeTo" //${cardVault.nativeAsset.symbol}"
val decodedKey = Base64.getDecoder().decode(hmacKey)
val mac = Mac.getInstance("HmacSHA256")
val secretKeySpec = SecretKeySpec(decodedKey, "HmacSHA256")
mac.init(secretKeySpec)
val signatureBytes = mac.doFinal(query.toByteArray(Charsets.UTF_8))
val signature = Base64.getEncoder().encodeToString(signatureBytes)
val encodedSignature = URLEncoder.encode(signature, "UTF-8")

paybisUrl = "$uri$query&signature=$encodedSignature"
}

DisplayDataView(
navController = navController,
vault = cardVault,
index = selectedVault,
title = R.string.addFunds,
label = stringResource(R.string.depositAddress),
data = cardVault.nativeAsset.address
data = cardVault.nativeAsset.address,
url = paybisUrl,
)
}

@RequiresApi(Build.VERSION_CODES.O)
@Preview(showBackground = true)
@Composable
fun AddFundsViewPreview() {
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/org/satochip/satodimeapp/ui/SettingsView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ fun SettingsView(navController: NavController, viewModel: SharedViewModel) {
SatodimeScreen.ShowLogsView.name
)
},
text = R.string.showLogs,
text = stringResource(R.string.showLogs),
)
Spacer(modifier = Modifier.weight(1f))

Expand All @@ -291,7 +291,7 @@ fun SettingsView(navController: NavController, viewModel: SharedViewModel) {
senderEmail = "support@satochip.io"
)
},
text = R.string.sendFeedback,
text = stringResource(R.string.sendFeedback),
buttonColor = SatoGreen
)
Spacer(modifier = Modifier.weight(1f))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ fun ShowPrivateKeyDataView(
data: String,
) {
val vaults = sharedViewModel.cardVaults
val vaultsSize = vaults?.size ?: 0
if (selectedVault > vaultsSize || vaults?.get(selectedVault - 1) == null) return
val vaultsSize = vaults.size
if (selectedVault > vaultsSize || vaults.get(selectedVault - 1) == null) return
val vault = vaults[selectedVault - 1]!!

// labels
Expand All @@ -47,7 +47,7 @@ fun ShowPrivateKeyDataView(
title = R.string.showPrivateKey,
label = labelString,
subLabel = subLabelString,
data = data
data = data,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ fun ThirdWelcomeViewContent() {
context = context
)
},
text = R.string.moreInfo,
text = stringResource(R.string.moreInfo),
textColor = Color.White,
buttonColor = LightGray
)
Expand All @@ -133,7 +133,7 @@ fun ThirdWelcomeViewContent() {
)
}
},
text = R.string.videoInfo,
text = stringResource(R.string.videoInfo),
textColor = Color.White,
buttonColor = SatoGreen
)
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/java/org/satochip/satodimeapp/ui/VaultsView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
Expand All @@ -27,6 +28,7 @@ import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.PageSize
import androidx.compose.foundation.pager.PagerState
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ButtonDefaults
Expand Down Expand Up @@ -425,6 +427,7 @@ fun DetailedVaultView(
) {
// VAULT CARD
VaultCards(pagerState, vaults, selectedCard, onAddVault)
val scrollState = rememberScrollState()

// ACTIONS ROW
Row(
Expand All @@ -434,6 +437,7 @@ fun DetailedVaultView(
.padding(10.dp)
.fillMaxWidth()
.height(120.dp)
.horizontalScroll(scrollState)
) {

if (selectedCard <= vaults.size
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Card
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
Expand All @@ -22,6 +24,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.paint
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontFamily
Expand All @@ -34,6 +37,7 @@ import org.satochip.satodimeapp.R
import org.satochip.satodimeapp.data.CardVault
import org.satochip.satodimeapp.data.SlotState
import org.satochip.satodimeapp.ui.components.shared.HeaderRow
import org.satochip.satodimeapp.ui.components.shared.SatoButton

private val topBoxHeight = 225.dp

Expand All @@ -45,10 +49,12 @@ fun DisplayDataView(
title: Int,
label: String,
subLabel: String = "",
data: String
data: String,
url: String? = null,
) {
//TODO: in entropy, show utf8 if possible, and sha256 of entropy should match privkey?

val scrollState = rememberScrollState()
val uriHandler = LocalUriHandler.current
Box(
modifier = Modifier
.fillMaxWidth()
Expand Down Expand Up @@ -100,7 +106,8 @@ fun DisplayDataView(
Card(
modifier = Modifier
.padding(top = topBoxHeight - 50.dp)
.fillMaxSize(),
.fillMaxSize()
.verticalScroll(scrollState),
shape = RoundedCornerShape(25.dp, 25.dp, 0.dp, 0.dp)
) {
Column(
Expand Down Expand Up @@ -133,6 +140,7 @@ fun DisplayDataView(
text = data
)
DataAsQrCode(data)

if(vault.state == SlotState.SEALED) {
Text(
modifier = Modifier
Expand All @@ -143,6 +151,22 @@ fun DisplayDataView(
style = MaterialTheme.typography.body1,
text = stringResource(R.string.youOrAnybodyCanDepositFunds)
)

if (url != null) {
SatoButton(
onClick = { uriHandler.openUri(url) },
text = stringResource( id = R.string.buy) + " ${vault.nativeAsset.symbol}",
)
Text(
modifier = Modifier
.padding(20.dp),
textAlign = TextAlign.Center,
color = MaterialTheme.colors.secondaryVariant,
fontSize = 16.sp,
style = MaterialTheme.typography.body1,
text = stringResource( id = R.string.buyInfo)
)
}
} else {
Spacer(Modifier.weight(1f))
}
Expand Down
Loading