Initial commit: Pezkuwi Wallet Android

Security hardened release:
- Code obfuscation enabled (minifyEnabled=true, shrinkResources=true)
- Sensitive files excluded (google-services.json, keystores)
- Branch.io key moved to BuildConfig placeholder
- Updated dependencies: OkHttp 4.12.0, Gson 2.10.1, BouncyCastle 1.77
- Comprehensive ProGuard rules for crypto wallet
- Navigation 2.7.7, Lifecycle 2.7.0, ConstraintLayout 2.1.4
This commit is contained in:
2026-02-12 05:19:41 +03:00
commit a294aa1a6b
7687 changed files with 441811 additions and 0 deletions
+41
View File
@@ -0,0 +1,41 @@
apply plugin: 'kotlin-parcelize'
android {
namespace 'io.novafoundation.nova.feature_bridge_impl'
buildFeatures {
viewBinding = true
}
}
dependencies {
implementation coroutinesDep
implementation project(':runtime')
implementation project(":feature-account-api")
implementation project(":feature-wallet-api")
implementation project(":feature-bridge-api")
implementation project(":common")
implementation materialDep
implementation daggerDep
ksp daggerCompiler
implementation substrateSdkDep
implementation androidDep
implementation constraintDep
implementation lifeCycleKtxDep
implementation viewModelKtxDep
implementation coroutinesDep
implementation coroutinesAndroidDep
// QR Code generation
implementation zXingCoreDep
api project(':core-api')
testImplementation project(':test-shared')
}
@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>
@@ -0,0 +1,31 @@
package io.novafoundation.nova.feature_bridge_impl.di
import dagger.Component
import io.novafoundation.nova.common.di.CommonApi
import io.novafoundation.nova.common.di.scope.FeatureScope
import io.novafoundation.nova.feature_bridge_api.di.BridgeFeatureApi
import io.novafoundation.nova.feature_bridge_impl.presentation.deposit.BridgeDepositFragment
@Component(
dependencies = [
BridgeFeatureDependencies::class
],
modules = [
BridgeFeatureModule::class
]
)
@FeatureScope
interface BridgeFeatureComponent : BridgeFeatureApi {
fun inject(fragment: BridgeDepositFragment)
@Component.Factory
interface Factory {
fun create(
dependencies: BridgeFeatureDependencies
): BridgeFeatureComponent
}
@Component(dependencies = [CommonApi::class])
interface BridgeFeatureDependenciesComponent : BridgeFeatureDependencies
}
@@ -0,0 +1,8 @@
package io.novafoundation.nova.feature_bridge_impl.di
import android.content.Context
interface BridgeFeatureDependencies {
fun context(): Context
}
@@ -0,0 +1,14 @@
package io.novafoundation.nova.feature_bridge_impl.di
import dagger.Module
import dagger.Provides
import io.novafoundation.nova.common.di.scope.FeatureScope
import io.novafoundation.nova.feature_bridge_api.domain.model.BridgeConfig
@Module
class BridgeFeatureModule {
@Provides
@FeatureScope
fun provideBridgeConfig(): BridgeConfig = BridgeConfig.DEFAULT
}
@@ -0,0 +1,124 @@
package io.novafoundation.nova.feature_bridge_impl.presentation.deposit
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.graphics.Bitmap
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import com.google.zxing.BarcodeFormat
import com.google.zxing.qrcode.QRCodeWriter
import io.novafoundation.nova.feature_bridge_api.domain.model.BridgeConfig
import io.novafoundation.nova.feature_bridge_impl.databinding.FragmentBridgeDepositBinding
import kotlinx.coroutines.launch
/**
* Bridge Deposit Screen
*
* Shows the Polkadot Asset Hub address where users should send USDT
* to receive wUSDT on Pezkuwi Asset Hub.
*/
class BridgeDepositFragment : Fragment() {
private var _binding: FragmentBridgeDepositBinding? = null
private val binding get() = _binding!!
private val bridgeConfig = BridgeConfig.DEFAULT
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentBridgeDepositBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupUI()
generateQRCode()
}
private fun setupUI() {
with(binding) {
// Set bridge address
bridgeAddressText.text = bridgeConfig.polkadotDepositAddress
// Set info text
minDepositText.text = "Minimum: ${bridgeConfig.minDeposit} USDT"
feeText.text = "Fee: ${bridgeConfig.feePercentage}"
// Copy button
copyAddressButton.setOnClickListener {
copyToClipboard(bridgeConfig.polkadotDepositAddress)
}
// Address text click also copies
bridgeAddressText.setOnClickListener {
copyToClipboard(bridgeConfig.polkadotDepositAddress)
}
// Back button
backButton.setOnClickListener {
requireActivity().onBackPressed()
}
}
}
private fun generateQRCode() {
lifecycleScope.launch {
try {
val qrCodeWriter = QRCodeWriter()
val bitMatrix = qrCodeWriter.encode(
bridgeConfig.polkadotDepositAddress,
BarcodeFormat.QR_CODE,
512,
512
)
val width = bitMatrix.width
val height = bitMatrix.height
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565)
for (x in 0 until width) {
for (y in 0 until height) {
val color = if (bitMatrix.get(x, y)) {
android.graphics.Color.BLACK
} else {
android.graphics.Color.WHITE
}
bitmap.setPixel(x, y, color)
}
}
binding.qrCodeImage.setImageBitmap(bitmap)
} catch (e: Exception) {
// QR code generation failed, hide the image
binding.qrCodeImage.visibility = View.GONE
}
}
}
private fun copyToClipboard(text: String) {
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clip = ClipData.newPlainText("Bridge Address", text)
clipboard.setPrimaryClip(clip)
Toast.makeText(requireContext(), "Address copied!", Toast.LENGTH_SHORT).show()
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
companion object {
fun newInstance() = BridgeDepositFragment()
}
}
@@ -0,0 +1,105 @@
package io.novafoundation.nova.feature_bridge_impl.presentation.status
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import io.novafoundation.nova.feature_bridge_api.domain.model.BridgeConfig
import io.novafoundation.nova.feature_bridge_api.domain.model.BridgeStatus
import io.novafoundation.nova.feature_bridge_impl.databinding.FragmentBridgeStatusBinding
import java.math.BigDecimal
/**
* Bridge Status Screen
*
* Shows the current bridge backing status, reserves, and transparency info.
*/
class BridgeStatusFragment : Fragment() {
private var _binding: FragmentBridgeStatusBinding? = null
private val binding get() = _binding!!
private val bridgeConfig = BridgeConfig.DEFAULT
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentBridgeStatusBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupUI()
loadStatus()
}
private fun setupUI() {
with(binding) {
backButton.setOnClickListener {
requireActivity().onBackPressed()
}
}
}
private fun loadStatus() {
// In production, this would fetch real data from the chain
// For now, show placeholder data
val status = BridgeStatus(
totalUsdtBacking = BigDecimal("0"),
totalWusdtCirculating = BigDecimal("0"),
isOperational = true,
lastSyncTimestamp = System.currentTimeMillis()
)
displayStatus(status)
}
private fun displayStatus(status: BridgeStatus) {
with(binding) {
// Backing ratio
backingRatioText.text = "${status.backingRatio.setScale(2)}%"
backingRatioText.setTextColor(
if (status.isFullyBacked) {
resources.getColor(io.novafoundation.nova.feature_bridge_impl.R.color.bridge_success, null)
} else {
resources.getColor(io.novafoundation.nova.feature_bridge_impl.R.color.bridge_error, null)
}
)
// Backing details
usdtBackingText.text = "${status.totalUsdtBacking} USDT"
wusdtCirculatingText.text = "${status.totalWusdtCirculating} wUSDT"
reserveText.text = "${status.reserve} USDT"
// Bridge config
polkadotAddressText.text = bridgeConfig.polkadotDepositAddress
pezkuwiAddressText.text = bridgeConfig.pezkuwiAddress
feeText.text = bridgeConfig.feePercentage
minDepositText.text = "${bridgeConfig.minDeposit} USDT"
// Status
statusIndicator.setBackgroundColor(
if (status.isOperational) {
resources.getColor(io.novafoundation.nova.feature_bridge_impl.R.color.bridge_success, null)
} else {
resources.getColor(io.novafoundation.nova.feature_bridge_impl.R.color.bridge_error, null)
}
)
statusText.text = if (status.isOperational) "Operational" else "Offline"
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
companion object {
fun newInstance() = BridgeStatusFragment()
}
}
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/bridge_address_background" />
<corners android:radius="8dp" />
</shape>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/bridge_success" />
</shape>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FFFFFF"
android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z" />
</vector>
@@ -0,0 +1,179 @@
<?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"
android:background="@color/bridge_background"
android:padding="16dp">
<!-- Back Button -->
<ImageButton
android:id="@+id/backButton"
android:layout_width="48dp"
android:layout_height="48dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_arrow_back"
android:contentDescription="Back"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tint="@color/bridge_text_primary" />
<!-- Title -->
<TextView
android:id="@+id/titleText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="48dp"
android:gravity="center"
android:text="Deposit USDT"
android:textColor="@color/bridge_text_primary"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@id/backButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/backButton"
app:layout_constraintTop_toTopOf="@id/backButton" />
<!-- Card Container -->
<androidx.cardview.widget.CardView
android:id="@+id/depositCard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
app:cardBackgroundColor="@color/bridge_card_background"
app:cardCornerRadius="16dp"
app:cardElevation="4dp"
app:layout_constraintTop_toBottomOf="@id/backButton">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="24dp">
<!-- Instructions -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Send USDT (Polkadot Asset Hub) to this address to receive wUSDT on Pezkuwi"
android:textColor="@color/bridge_text_secondary"
android:textSize="14sp" />
<!-- QR Code -->
<ImageView
android:id="@+id/qrCodeImage"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_marginTop="24dp"
android:background="#FFFFFF"
android:padding="8dp"
android:contentDescription="QR Code" />
<!-- Address Label -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="Bridge Address (Polkadot)"
android:textColor="@color/bridge_text_secondary"
android:textSize="12sp" />
<!-- Address -->
<TextView
android:id="@+id/bridgeAddressText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:background="@drawable/bg_address_field"
android:fontFamily="monospace"
android:padding="12dp"
android:textColor="@color/bridge_text_primary"
android:textIsSelectable="true"
android:textSize="13sp"
tools:text="16dSTc3BexjQKiPta7yNncF8nio4YgDQiPbudHzkuh7XJi8K" />
<!-- Copy Button -->
<com.google.android.material.button.MaterialButton
android:id="@+id/copyAddressButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Copy Address"
android:textAllCaps="false"
app:backgroundTint="@color/bridge_accent"
app:cornerRadius="8dp" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<!-- Info Card -->
<androidx.cardview.widget.CardView
android:id="@+id/infoCard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
app:cardBackgroundColor="@color/bridge_card_background"
app:cardCornerRadius="16dp"
app:cardElevation="4dp"
app:layout_constraintTop_toBottomOf="@id/depositCard">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Bridge Info"
android:textColor="@color/bridge_text_primary"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/minDepositText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textColor="@color/bridge_text_secondary"
android:textSize="14sp"
tools:text="Minimum: 10 USDT" />
<TextView
android:id="@+id/feeText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textColor="@color/bridge_text_secondary"
android:textSize="14sp"
tools:text="Fee: 0.1%" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="wUSDT will be sent to your Pezkuwi address automatically after confirmation."
android:textColor="@color/bridge_text_secondary"
android:textSize="12sp" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<!-- Backing Info -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center"
android:text="wUSDT is 1:1 backed by real USDT on Polkadot Asset Hub"
android:textColor="@color/bridge_text_secondary"
android:textSize="12sp"
app:layout_constraintTop_toBottomOf="@id/infoCard" />
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -0,0 +1,329 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
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"
android:background="@color/bridge_background">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp">
<!-- Back Button -->
<ImageButton
android:id="@+id/backButton"
android:layout_width="48dp"
android:layout_height="48dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_arrow_back"
android:contentDescription="Back"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tint="@color/bridge_text_primary" />
<!-- Title -->
<TextView
android:id="@+id/titleText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Bridge Status"
android:textColor="@color/bridge_text_primary"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@id/backButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/backButton"
app:layout_constraintTop_toTopOf="@id/backButton" />
<!-- Status Indicator Card -->
<androidx.cardview.widget.CardView
android:id="@+id/statusCard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
app:cardBackgroundColor="@color/bridge_card_background"
app:cardCornerRadius="16dp"
app:cardElevation="4dp"
app:layout_constraintTop_toBottomOf="@id/backButton">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
android:padding="24dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<View
android:id="@+id/statusIndicator"
android:layout_width="12dp"
android:layout_height="12dp"
android:background="@drawable/bg_status_indicator" />
<TextView
android:id="@+id/statusText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:textColor="@color/bridge_text_primary"
android:textSize="16sp"
tools:text="Operational" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Backing Ratio"
android:textColor="@color/bridge_text_secondary"
android:textSize="14sp" />
<TextView
android:id="@+id/backingRatioText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/bridge_success"
android:textSize="48sp"
android:textStyle="bold"
tools:text="100.00%" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<!-- Backing Details Card -->
<androidx.cardview.widget.CardView
android:id="@+id/backingCard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
app:cardBackgroundColor="@color/bridge_card_background"
app:cardCornerRadius="16dp"
app:cardElevation="4dp"
app:layout_constraintTop_toBottomOf="@id/statusCard">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Backing Details"
android:textColor="@color/bridge_text_primary"
android:textSize="16sp"
android:textStyle="bold" />
<!-- USDT Backing -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="USDT in Reserve"
android:textColor="@color/bridge_text_secondary"
android:textSize="14sp" />
<TextView
android:id="@+id/usdtBackingText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/bridge_text_primary"
android:textSize="14sp"
tools:text="10,000 USDT" />
</LinearLayout>
<!-- wUSDT Circulating -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="wUSDT Circulating"
android:textColor="@color/bridge_text_secondary"
android:textSize="14sp" />
<TextView
android:id="@+id/wusdtCirculatingText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/bridge_text_primary"
android:textSize="14sp"
tools:text="9,990 wUSDT" />
</LinearLayout>
<!-- Reserve (Fees) -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Excess Reserve (Fees)"
android:textColor="@color/bridge_text_secondary"
android:textSize="14sp" />
<TextView
android:id="@+id/reserveText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/bridge_accent"
android:textSize="14sp"
tools:text="10 USDT" />
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
<!-- Bridge Config Card -->
<androidx.cardview.widget.CardView
android:id="@+id/configCard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
app:cardBackgroundColor="@color/bridge_card_background"
app:cardCornerRadius="16dp"
app:cardElevation="4dp"
app:layout_constraintTop_toBottomOf="@id/backingCard">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Bridge Configuration"
android:textColor="@color/bridge_text_primary"
android:textSize="16sp"
android:textStyle="bold" />
<!-- Polkadot Address -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="Polkadot Deposit Address"
android:textColor="@color/bridge_text_secondary"
android:textSize="12sp" />
<TextView
android:id="@+id/polkadotAddressText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="monospace"
android:textColor="@color/bridge_text_primary"
android:textIsSelectable="true"
android:textSize="11sp"
tools:text="16dSTc3BexjQKiPta7yNncF8nio4YgDQiPbudHzkuh7XJi8K" />
<!-- Pezkuwi Address -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="Pezkuwi Bridge Address"
android:textColor="@color/bridge_text_secondary"
android:textSize="12sp" />
<TextView
android:id="@+id/pezkuwiAddressText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="monospace"
android:textColor="@color/bridge_text_primary"
android:textIsSelectable="true"
android:textSize="11sp"
tools:text="5Hh9KGn7oBTvtBPNcUvNeTQyw6oQrNfGdtsRU11QMc618Rse" />
<!-- Fee -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Bridge Fee"
android:textColor="@color/bridge_text_secondary"
android:textSize="14sp" />
<TextView
android:id="@+id/feeText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/bridge_text_primary"
android:textSize="14sp"
tools:text="0.1%" />
</LinearLayout>
<!-- Min Deposit -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Minimum Deposit"
android:textColor="@color/bridge_text_secondary"
android:textSize="14sp" />
<TextView
android:id="@+id/minDepositText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/bridge_text_primary"
android:textSize="14sp"
tools:text="10 USDT" />
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
<!-- Transparency Note -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="32dp"
android:gravity="center"
android:text="All bridge transactions are verifiable on-chain.\nwUSDT is always 1:1 backed by real USDT."
android:textColor="@color/bridge_text_secondary"
android:textSize="12sp"
app:layout_constraintTop_toBottomOf="@id/configCard" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Bridge Feature Colors -->
<color name="bridge_background">#121212</color>
<color name="bridge_card_background">#1E1E1E</color>
<color name="bridge_text_primary">#FFFFFF</color>
<color name="bridge_text_secondary">#B3B3B3</color>
<color name="bridge_accent">#00D395</color>
<color name="bridge_accent_dark">#00A676</color>
<color name="bridge_warning">#FFB800</color>
<color name="bridge_error">#FF4444</color>
<color name="bridge_success">#00D395</color>
<color name="bridge_address_background">#2A2A2A</color>
</resources>