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

Token added functionality,balance and price of all tokens #118

Merged
merged 5 commits into from
Nov 2, 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
9 changes: 9 additions & 0 deletions wallet_app/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,14 @@ dependencies {
implementation(libs.androidx.hilt.navigation.fragment)
implementation (libs.androidx.hilt.navigation.compose.v100alpha03)

implementation("androidx.room:room-runtime:2.6.1")
kapt("androidx.room:room-compiler:2.6.1")
implementation("androidx.room:room-ktx:2.6.1")

// image loader
implementation("io.coil-kt:coil-compose:2.6.0")
implementation("com.github.skydoves:landscapist-glide:1.3.7")
implementation("io.coil-kt:coil-gif:2.6.0")

implementation(libs.androidx.ui.tooling.preview)
debugImplementation(libs.androidx.ui.tooling)
Expand All @@ -131,6 +139,7 @@ dependencies {
implementation(libs.androidx.navigation.compose)



implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
Expand Down
1 change: 1 addition & 0 deletions wallet_app/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<uses-permission android:name="android.permission.INTERNET" />

<application
android:name=".WalletAppApplication"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.example.walletapp

import android.app.Application
import com.example.walletapp.db.TokenDatabase


class WalletAppApplication : Application() {

// Lazy initialization of the database
val database: TokenDatabase by lazy { TokenDatabase.getDatabase(this) }
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package com.example.walletapp.data.coins

import com.example.walletapp.model.CoinData
import com.example.walletapp.model.TokenIdsResponse
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Headers
import retrofit2.http.Path
import retrofit2.http.Query

typealias GetTokenPriceResponse = Response<Map<String, Map<String, Double>>>;
Expand All @@ -17,4 +20,16 @@ interface CoinGeckoApi {
@Query("ids") ids: String, // Comma-separated token IDs
@Query("vs_currencies") vsCurrencies: String // Comma-separated currency codes
): GetTokenPriceResponse


@Headers(
"accept: application/json",
"x-cg-demo-api-key: CG-mRdWfNFoZnKVan4GNdTrhZjL"
)
@GET("coins/list")
suspend fun getTokenIds(@Query("include_platform") includePlatform:Boolean):TokenIdsResponse

@Headers("accept: application/json", "x-cg-demo-api-key: CG-mRdWfNFoZnKVan4GNdTrhZjL")
@GET("coins/{id}")
suspend fun getTokenData(@Path("id") id: String,): Response<CoinData>
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@


package com.example.walletapp.data.coins

import com.example.walletapp.di.RetrofitClient
import com.example.walletapp.model.CoinData
import com.example.walletapp.model.TokenIdsResponse
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import retrofit2.Response

class CoinRepository {

suspend fun getTokenPrices(
ids: String,
vsCurrencies: String
Expand All @@ -13,4 +19,17 @@ class CoinRepository {
RetrofitClient.apiService.getTokenPrices(ids, vsCurrencies)
}
}
}

suspend fun getTokenIds(
): TokenIdsResponse {
return withContext(Dispatchers.IO) {
RetrofitClient.apiService.getTokenIds(false)
}
}

suspend fun getTokenData(id:String):Response<CoinData>{
return withContext(Dispatchers.IO) {
RetrofitClient.apiService.getTokenData(id)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.example.walletapp.db


import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import com.example.walletapp.model.Token
import kotlinx.coroutines.flow.Flow
import androidx.room.Query

@Dao
interface TokenDao {

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(token: Token)

@Query("SELECT * FROM token_table")
fun getAllTokens(): Flow<List<Token>>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.example.walletapp.db

import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import androidx.sqlite.db.SupportSQLiteDatabase
import com.example.walletapp.model.Token
import com.example.walletapp.utils.Converters
import com.swmansion.starknet.data.types.Felt
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

@Database(entities = [Token::class], version = 2, exportSchema = false)
@TypeConverters(Converters::class)
abstract class TokenDatabase : RoomDatabase() {

abstract fun tokenDao(): TokenDao

companion object {
@Volatile
private var INSTANCE: TokenDatabase? = null

fun getDatabase(context: Context): TokenDatabase {
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
TokenDatabase::class.java,
"token_database"
)
.addCallback(DatabaseCallback()) // Add callback here
.build()
INSTANCE = instance
instance
}
}
}

private class DatabaseCallback : RoomDatabase.Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
INSTANCE?.let { database ->
CoroutineScope(Dispatchers.IO).launch {
populateDatabase(database.tokenDao())
}
}
}

suspend fun populateDatabase(tokenDao: TokenDao) {
// Add default tokens
val token1 = Token(contactAddress = Felt.fromHex("0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7"), name = "ethereum", symbol = "eth", decimals = 18,tokenId="ethereum")
val token2 = Token(contactAddress = Felt.fromHex("0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d"), name = "starknet", symbol = "strk", decimals = 18,tokenId="starknet")
tokenDao.insert(token1)
tokenDao.insert(token2)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.example.walletapp.model

import com.google.gson.annotations.SerializedName

data class CoinData(
@SerializedName("id") val id: String,
@SerializedName("symbol") val symbol: String,
@SerializedName("name") val name: String,
@SerializedName("web_slug") val webSlug: String,
@SerializedName("asset_platform_id") val assetPlatformId: String,
@SerializedName("image") val image: ImageData,
@SerializedName("contract_address") val contractAddress: String
)

data class ImageData(
@SerializedName("thumb") val thumb: String,
@SerializedName("small") val small: String,
@SerializedName("large") val large: String
)
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
package com.example.walletapp.model

class Token (
val address: String,
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.swmansion.starknet.data.types.Felt

@Entity(tableName = "token_table")
data class Token(
@PrimaryKey(autoGenerate = true) val id: Int = 0,
val contactAddress: Felt,
val name: String,
val symbol: String,
val name: String
val decimals: Int,
val tokenId:String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.example.walletapp.model

class TokenIdsResponse : ArrayList<TokenIdsResponseItem>()
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.example.walletapp.model

data class TokenIdsResponseItem(
val id: String,
val name: String,
val symbol: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.core.view.WindowCompat
import androidx.lifecycle.ViewModelProvider
import com.example.walletapp.BuildConfig
import com.example.walletapp.WalletAppApplication
import com.example.walletapp.ui.account.TokenRepository
import com.example.walletapp.ui.account.TokenViewModel
import com.example.walletapp.utils.StarknetClient

class MainActivity : ComponentActivity() {
Expand All @@ -23,10 +27,16 @@ class MainActivity : ComponentActivity() {
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Access the database instance
val database = (application as WalletAppApplication).database
val repository = TokenRepository(database.tokenDao())
val tokenViewModel: TokenViewModel = ViewModelProvider(
this, TokenViewModel.Factory(application,repository)
).get(TokenViewModel::class.java)
enableEdgeToEdge()
WindowCompat.setDecorFitsSystemWindows(window, true)
setContent {
WalletApp()
WalletApp(tokenViewModel)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import com.example.walletapp.ui.account.AddTokenScreen
import com.example.walletapp.ui.account.TokenViewModel
import com.example.walletapp.ui.account.WalletScreen
import com.example.walletapp.ui.activity.FinalizeAccountCreationScreen
import com.example.walletapp.ui.onboarding.CreateAccountScreen
Expand Down Expand Up @@ -42,7 +43,7 @@ object Send
object Receive

@Composable
fun WalletApp() {
fun WalletApp(tokenViewModel: TokenViewModel) {
WalletappTheme {

// TODO(#109): get this information from a data store
Expand Down Expand Up @@ -90,11 +91,13 @@ fun WalletApp() {
WalletScreen(
onNewTokenPress = { navController.navigate( route = AddToken ) },
onReceivePress = { navController.navigate( route = Receive ) },
onSendPress = { navController.navigate( route = Send ) }
onSendPress = { navController.navigate( route = Send ) },
tokenViewModel = tokenViewModel
)
}
composable<AddToken> {
AddTokenScreen(
tokenViewModel=tokenViewModel,
onConfirm = { navController.navigateUp() }
)
}
Expand Down
Loading
Loading