Skip to content

Commit

Permalink
Fixed walletId problem in transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
Dev-Pasaka committed Jan 6, 2025
1 parent b3cdda1 commit 042506a
Show file tree
Hide file tree
Showing 12 changed files with 93 additions and 129 deletions.
105 changes: 89 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,96 @@
This is a Kotlin Multiplatform project targeting Android, Web, Desktop, Server.
# Multiplatform Crypto Wallet (SmartPesa)

* `/composeApp` is for code that will be shared across your Compose Multiplatform applications.
It contains several subfolders:
- `commonMain` is for code that’s common for all targets.
- Other folders are for Kotlin code that will be compiled for only the platform indicated in the folder name.
For example, if you want to use Apple’s CoreCrypto for the iOS part of your Kotlin app,
`iosMain` would be the right folder for such calls.
## Overview
**SmartPesa** is an innovative, Kotlin Multiplatform (KMP)-based open-source project designed to revolutionize cryptocurrency wallet management across multiple platforms. By leveraging advanced KMP technology, SmartPesa ensures a seamless and secure experience for users, enabling effortless transactions by simply scanning a QR code.

* `/server` is for the Ktor server application.
### Key Features
- **Error-Free Transactions**: Avoid wallet address errors with QR code-based transactions.
- **Enhanced Security**: Mitigate wallet poisoning attacks in crypto markets.
- **User-Friendly**: Designed for both crypto newcomers and seasoned users.
- **Financial Inclusion**: Focused on empowering unbanked and underbanked populations, particularly in Sub-Saharan Africa.

* `/shared` is for the code that will be shared between all targets in the project.
The most important subfolder is `commonMain`. If preferred, you can add code to the platform-specific folders here too.
### Components
SmartPesa comprises:
1. A **Ktor-based server** integrating with **Circle.io** for:
- Programmable wallets
- Transaction processing
- Wallet management
2. A **Kotlin Multiplatform Android application** for seamless mobile wallet management.
3. A **desktop application** offering extended functionality and accessibility.

---

Learn more about [Kotlin Multiplatform](https://www.jetbrains.com/help/kotlin-multiplatform-dev/get-started.html),
[Compose Multiplatform](https://github.com/JetBrains/compose-multiplatform/#compose-multiplatform),
[Kotlin/Wasm](https://kotl.in/wasm/)
## Ktor Server Setup

We would appreciate your feedback on Compose/Web and Kotlin/Wasm in the public Slack channel [#compose-web](https://slack-chats.kotlinlang.org/c/compose-web).
If you face any issues, please report them on [GitHub](https://github.com/JetBrains/compose-multiplatform/issues).
### Local Environment Setup
To configure the Ktor server locally:

1. Create a `.env` file in the root directory of the server module and add the following configurations:

```env
# Circle Programmable Wallets Configuration
API_KEY=TEST_API_KEY # Replace with Circle's test API key
ENTITY_SECRETE=circle_entity_secret
# JWT Configuration
JWT_SECRETE=your_own_jwt_secret
# MongoDB Configuration
MONGODBUSERNAME=your_mongodb_username
MONGODBPASSWORD=your_mongodb_password
DATABASENAME=your_mongodb_database_name
```
2. Add the .env file variables to your development environment (e.g., IntelliJ IDEA or Android Studio).
3. Run the server application. The server will start on port 8081.
4. Create mongodb database from mongodb atlas for free and quick setup or modify the database url build to work with your local mongodb.

## Docker Setup
You can also deploy the server using Docker for faster and more consistent setup.

Docker Compose File
Create a docker-compose.yml file with the following content:
```yaml
version: '3.8'

services:
smartpesa:
image: pascarl/smartpesa:latest
container_name: smartpesa-app
ports:
- "8080:8081"
env_file:
- .env
restart: unless-stopped
networks:
- smartpesa-network
volumes:
- ./app_data:/app_data

networks:
smartpesa-network:
driver: bridge

```
## Live Test
To test the server, a live deployment has been made on an AWS EC2 instance for free testing.
You can access the server using the following base URL

Base URL: http://52.57.41.193

You can also get the api documentation [here](https://documenter.getpostman.com/view/27366427/2sAYJ7hKUB)

## CI/CD
To save time managing deployments i wanted to automate that part so with docker,
docker hub and github actions i was able to automate that part. This saved me lots
of time a nd helped me reduce deployments errors and bugs.
How ever i faced challenge when i tried to use ktor in build docker plugin. for some
reason i was anable to use the docker plugin to build and genrate the docker images. but the funny thing is
i only experience this problem withing kmp project but as ktor stand alone everything was working well
so i revolted to building my own dockerfile which you can find it at the root of the project.

I tweeted the issue on x maybet @jetbrains team might follow it up. here is the [tweet](https://x.com/pasaka254/status/1867994507658379280)

Then the github workflows are in the .github directory in the root folder. you will find build-image.yml
for building the docker image and publishing it to dockerhub, and deploy-to-ec2.yml for deploying the image
to aws ec2 instance. make sure you server is configured with docker and docker-compose.

You can open the web application by running the `:composeApp:wasmJsBrowserDevelopmentRun` Gradle task.# MultipltformCryptoWallet
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package org.example.di

import androidx.lifecycle.viewmodel.compose.viewModel
import org.example.presentation.screens.AuthScreen.AuthScreenViewModel
import org.example.presentation.screens.dashboardScreen.DashboardScreenViewModel
import org.example.presentation.screens.onBoarding.OnBoardingScreenViewModel
import org.example.presentation.screens.splashScreen.SplashScreenViewModel
Expand All @@ -10,7 +8,6 @@ import org.koin.dsl.module

val viewModelsModule = module {
single{SplashScreenViewModel(get())}
single{AuthScreenViewModel()}
single{OnBoardingScreenViewModel(get(), get())}
single{TransferScreenViewModel(get())}
single{DashboardScreenViewModel(get(), get(), get())}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.toRoute
import org.example.presentation.screens.AuthScreen.AuthScreen
import org.example.presentation.screens.QrCodeScannerScreen
import org.example.presentation.screens.dashboardScreen.DashBoardScreen
import org.example.presentation.screens.explorer.ExplorerScreen
Expand Down Expand Up @@ -54,9 +53,6 @@ fun NavGraph(
}
)
}
composable<Screen.AuthScreen> {
AuthScreen()
}
composable<Screen.OnBoarding> {
OnBoardingScreen(
onNavigateToDashboard = {
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -124,24 +124,7 @@ class DashboardScreenViewModel(
transactionsState = transactionsState.copy(
isLoading = false,
isSuccessful = true,
transactions = result.data?.map{transaction->
var transactionData = transaction
walletState.wallets.forEach{wallet->
transactionData = if (wallet.address == transaction.senderAddress){
transaction.copy(
transactionType = "OUT"
)
}
else if (wallet.address == transaction.receiverAddress){
transaction.copy(
transactionType = "IN"
)
}
else transaction
}
transactionData

} ?: emptyList()
transactions = result.data ?: emptyList()
)
println("Success: ${result.data}")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import kotlinx.coroutines.launch
import org.example.domain.model.WalletSecrete
import org.example.presentation.screens.onBoarding.components.CreateWalletBottomSheetContent
import org.example.presentation.screens.onBoarding.components.ImportWalletBottomSheet
import org.example.presentation.screens.onBoarding.components.OnBoardingScreenUpperSection

@OptIn(ExperimentalMaterial3Api::class)
@Composable
Expand Down Expand Up @@ -100,14 +99,6 @@ fun OnBoardingScreen(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Top
) {
OnBoardingScreenUpperSection(
actionRegister = {

},
actionSignIn = {

}
)
OnBoardingScreenMiddleSection(
items = viewModel.onBoardingData
)
Expand Down

This file was deleted.

Binary file added screenshots/generating crypto payment request.mp4
Binary file not shown.
Binary file added screenshots/qr-code.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ class TransactionRepositoryImpl(
* */
val transaction = Transaction(
senderId = "",
walletId = wallet.walletId,
walletId = wallet.id,
tokenId = walletBalance.token.id,
amounts = listOf(body.amount.toString()),
senderAddress = wallet.address,
Expand Down
3 changes: 2 additions & 1 deletion server/src/main/resources/application.conf
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
ktor{
ktor {

server {
logger = "crypto-wallet"
apiVersion = "/api/v1"
Expand Down

0 comments on commit 042506a

Please sign in to comment.