diff --git a/app/build.gradle.kts b/app/build.gradle.kts deleted file mode 100644 index bedd3f7..0000000 --- a/app/build.gradle.kts +++ /dev/null @@ -1,97 +0,0 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile -import org.jlleitschuh.gradle.ktlint.reporter.ReporterType - -plugins { - id("com.android.application") version "9.2.0" - id("org.jetbrains.kotlin.plugin.compose") version "2.3.21" - id("org.jetbrains.kotlin.plugin.serialization") version "2.3.21" - id("org.jlleitschuh.gradle.ktlint") version "14.2.0" -} - -// This is the version of the app that is displayed in the UI on the drawer. -val variantName = "Version 0.1.0/Kyoto" - -android { - namespace = "org.bitcoindevkit.devkitwallet" - compileSdk = 37 - - buildFeatures { - viewBinding = true - compose = true - buildConfig = true - } - - defaultConfig { - applicationId = "org.bitcoindevkit.devkitwallet" - minSdk = 33 - targetSdk = 37 - versionCode = 1 - versionName = "v0.1.0" - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - - buildConfigField("String", "VARIANT_NAME", "\"$variantName\"") - } - - buildTypes { - getByName("debug") { - isDebuggable = true - } - } - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - } -} - -tasks.withType { - compilerOptions { - jvmTarget.set(JvmTarget.JVM_17) - } -} - -dependencies { - // Basic android dependencies - implementation("androidx.core:core-ktx:1.17.0") - implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.10.0") - implementation("androidx.core:core-splashscreen:1.2.0") - - // DataStore - implementation("androidx.datastore:datastore:1.2.1") - - // Jetpack Compose - // Adding the Bill of Materials synchronizes dependencies in the androidx.compose namespace - // You can remove the library version in your dependency declarations - implementation(platform("androidx.compose:compose-bom:2026.02.00")) - implementation("androidx.compose.animation:animation") - implementation("androidx.compose.ui:ui-tooling") - implementation("androidx.compose.ui:ui") - implementation("androidx.compose.material3:material3") - implementation("androidx.activity:activity-compose") - implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.10.0") - implementation("androidx.navigation:navigation-compose:2.9.7") - - // Icons - implementation("androidx.compose.material:material-icons-extended:1.7.8") - implementation("com.composables:icons-lucide:1.1.0") - - // Bitcoin Development Kit - implementation("org.bitcoindevkit:bdk-android:3.0.0") - - // QR codes - implementation("com.google.zxing:core:3.5.4") - - // Tests - testImplementation("junit:junit:4.13.2") - androidTestImplementation("androidx.test.ext:junit:1.3.0") - androidTestImplementation("androidx.test.espresso:espresso-core:3.7.0") -} - -ktlint { - version = "1.8.0" - ignoreFailures = false - reporters { - reporter(ReporterType.PLAIN).apply { outputToConsole = true } - } -} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro deleted file mode 100644 index ff59496..0000000 --- a/app/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/assets/bip39-english.txt b/app/src/main/assets/bip39-english.txt deleted file mode 100644 index f78ccaf..0000000 --- a/app/src/main/assets/bip39-english.txt +++ /dev/null @@ -1,2048 +0,0 @@ -abandon -ability -able -about -above -absent -absorb -abstract -absurd -abuse -access -accident -account -accuse -achieve -acid -acoustic -acquire -across -act -action -actor -actress -actual -adapt -add -addict -address -adjust -admit -adult -advance -advice -aerobic -affair -afford -afraid -again -age -agent -agree -ahead -aim -air -airport -aisle -alarm -album -alcohol -alert -alien -all -alley -allow -almost -alone -alpha -already -also -alter -always -amateur -amazing -among -amount -amused -analyst -anchor -ancient -anger -angle -angry -animal -ankle -announce -annual -another -answer -antenna -antique -anxiety -any -apart -apology -appear -apple -approve -april -arch -arctic -area -arena -argue -arm -armed -armor -army -around -arrange -arrest -arrive -arrow -art -artefact -artist -artwork -ask -aspect -assault -asset -assist -assume -asthma -athlete -atom -attack -attend -attitude -attract -auction -audit -august -aunt -author -auto -autumn -average -avocado -avoid -awake -aware -away -awesome -awful -awkward -axis -baby -bachelor -bacon -badge -bag -balance -balcony -ball -bamboo -banana -banner -bar -barely -bargain -barrel -base -basic -basket -battle -beach -bean -beauty -because -become -beef -before -begin -behave -behind -believe -below -belt -bench -benefit -best -betray -better -between -beyond -bicycle -bid -bike -bind -biology -bird -birth -bitter -black -blade -blame -blanket -blast -bleak -bless -blind -blood -blossom -blouse -blue -blur -blush -board -boat -body -boil -bomb -bone -bonus -book -boost -border -boring -borrow -boss -bottom -bounce -box -boy -bracket -brain -brand -brass -brave -bread -breeze -brick -bridge -brief -bright -bring -brisk -broccoli -broken -bronze -broom -brother -brown -brush -bubble -buddy -budget -buffalo -build -bulb -bulk -bullet -bundle -bunker -burden -burger -burst -bus -business -busy -butter -buyer -buzz -cabbage -cabin -cable -cactus -cage -cake -call -calm -camera -camp -can -canal -cancel -candy -cannon -canoe -canvas -canyon -capable -capital -captain -car -carbon -card -cargo -carpet -carry -cart -case -cash -casino -castle -casual -cat -catalog -catch -category -cattle -caught -cause -caution -cave -ceiling -celery -cement -census -century -cereal -certain -chair -chalk -champion -change -chaos -chapter -charge -chase -chat -cheap -check -cheese -chef -cherry -chest -chicken -chief -child -chimney -choice -choose -chronic -chuckle -chunk -churn -cigar -cinnamon -circle -citizen -city -civil -claim -clap -clarify -claw -clay -clean -clerk -clever -click -client -cliff -climb -clinic -clip -clock -clog -close -cloth -cloud -clown -club -clump -cluster -clutch -coach -coast -coconut -code -coffee -coil -coin -collect -color -column -combine -come -comfort -comic -common -company -concert -conduct -confirm -congress -connect -consider -control -convince -cook -cool -copper -copy -coral -core -corn -correct -cost -cotton -couch -country -couple -course -cousin -cover -coyote -crack -cradle -craft -cram -crane -crash -crater -crawl -crazy -cream -credit -creek -crew -cricket -crime -crisp -critic -crop -cross -crouch -crowd -crucial -cruel -cruise -crumble -crunch -crush -cry -crystal -cube -culture -cup -cupboard -curious -current -curtain -curve -cushion -custom -cute -cycle -dad -damage -damp -dance -danger -daring -dash -daughter -dawn -day -deal -debate -debris -decade -december -decide -decline -decorate -decrease -deer -defense -define -defy -degree -delay -deliver -demand -demise -denial -dentist -deny -depart -depend -deposit -depth -deputy -derive -describe -desert -design -desk -despair -destroy -detail -detect -develop -device -devote -diagram -dial -diamond -diary -dice -diesel -diet -differ -digital -dignity -dilemma -dinner -dinosaur -direct -dirt -disagree -discover -disease -dish -dismiss -disorder -display -distance -divert -divide -divorce -dizzy -doctor -document -dog -doll -dolphin -domain -donate -donkey -donor -door -dose -double -dove -draft -dragon -drama -drastic -draw -dream -dress -drift -drill -drink -drip -drive -drop -drum -dry -duck -dumb -dune -during -dust -dutch -duty -dwarf -dynamic -eager -eagle -early -earn -earth -easily -east -easy -echo -ecology -economy -edge -edit -educate -effort -egg -eight -either -elbow -elder -electric -elegant -element -elephant -elevator -elite -else -embark -embody -embrace -emerge -emotion -employ -empower -empty -enable -enact -end -endless -endorse -enemy -energy -enforce -engage -engine -enhance -enjoy -enlist -enough -enrich -enroll -ensure -enter -entire -entry -envelope -episode -equal -equip -era -erase -erode -erosion -error -erupt -escape -essay -essence -estate -eternal -ethics -evidence -evil -evoke -evolve -exact -example -excess -exchange -excite -exclude -excuse -execute -exercise -exhaust -exhibit -exile -exist -exit -exotic -expand -expect -expire -explain -expose -express -extend -extra -eye -eyebrow -fabric -face -faculty -fade -faint -faith -fall -false -fame -family -famous -fan -fancy -fantasy -farm -fashion -fat -fatal -father -fatigue -fault -favorite -feature -february -federal -fee -feed -feel -female -fence -festival -fetch -fever -few -fiber -fiction -field -figure -file -film -filter -final -find -fine -finger -finish -fire -firm -first -fiscal -fish -fit -fitness -fix -flag -flame -flash -flat -flavor -flee -flight -flip -float -flock -floor -flower -fluid -flush -fly -foam -focus -fog -foil -fold -follow -food -foot -force -forest -forget -fork -fortune -forum -forward -fossil -foster -found -fox -fragile -frame -frequent -fresh -friend -fringe -frog -front -frost -frown -frozen -fruit -fuel -fun -funny -furnace -fury -future -gadget -gain -galaxy -gallery -game -gap -garage -garbage -garden -garlic -garment -gas -gasp -gate -gather -gauge -gaze -general -genius -genre -gentle -genuine -gesture -ghost -giant -gift -giggle -ginger -giraffe -girl -give -glad -glance -glare -glass -glide -glimpse -globe -gloom -glory -glove -glow -glue -goat -goddess -gold -good -goose -gorilla -gospel -gossip -govern -gown -grab -grace -grain -grant -grape -grass -gravity -great -green -grid -grief -grit -grocery -group -grow -grunt -guard -guess -guide -guilt -guitar -gun -gym -habit -hair -half -hammer -hamster -hand -happy -harbor -hard -harsh -harvest -hat -have -hawk -hazard -head -health -heart -heavy -hedgehog -height -hello -helmet -help -hen -hero -hidden -high -hill -hint -hip -hire -history -hobby -hockey -hold -hole -holiday -hollow -home -honey -hood -hope -horn -horror -horse -hospital -host -hotel -hour -hover -hub -huge -human -humble -humor -hundred -hungry -hunt -hurdle -hurry -hurt -husband -hybrid -ice -icon -idea -identify -idle -ignore -ill -illegal -illness -image -imitate -immense -immune -impact -impose -improve -impulse -inch -include -income -increase -index -indicate -indoor -industry -infant -inflict -inform -inhale -inherit -initial -inject -injury -inmate -inner -innocent -input -inquiry -insane -insect -inside -inspire -install -intact -interest -into -invest -invite -involve -iron -island -isolate -issue -item -ivory -jacket -jaguar -jar -jazz -jealous -jeans -jelly -jewel -job -join -joke -journey -joy -judge -juice -jump -jungle -junior -junk -just -kangaroo -keen -keep -ketchup -key -kick -kid -kidney -kind -kingdom -kiss -kit -kitchen -kite -kitten -kiwi -knee -knife -knock -know -lab -label -labor -ladder -lady -lake -lamp -language -laptop -large -later -latin -laugh -laundry -lava -law -lawn -lawsuit -layer -lazy -leader -leaf -learn -leave -lecture -left -leg -legal -legend -leisure -lemon -lend -length -lens -leopard -lesson -letter -level -liar -liberty -library -license -life -lift -light -like -limb -limit -link -lion -liquid -list -little -live -lizard -load -loan -lobster -local -lock -logic -lonely -long -loop -lottery -loud -lounge -love -loyal -lucky -luggage -lumber -lunar -lunch -luxury -lyrics -machine -mad -magic -magnet -maid -mail -main -major -make -mammal -man -manage -mandate -mango -mansion -manual -maple -marble -march -margin -marine -market -marriage -mask -mass -master -match -material -math -matrix -matter -maximum -maze -meadow -mean -measure -meat -mechanic -medal -media -melody -melt -member -memory -mention -menu -mercy -merge -merit -merry -mesh -message -metal -method -middle -midnight -milk -million -mimic -mind -minimum -minor -minute -miracle -mirror -misery -miss -mistake -mix -mixed -mixture -mobile -model -modify -mom -moment -monitor -monkey -monster -month -moon -moral -more -morning -mosquito -mother -motion -motor -mountain -mouse -move -movie -much -muffin -mule -multiply -muscle -museum -mushroom -music -must -mutual -myself -mystery -myth -naive -name -napkin -narrow -nasty -nation -nature -near -neck -need -negative -neglect -neither -nephew -nerve -nest -net -network -neutral -never -news -next -nice -night -noble -noise -nominee -noodle -normal -north -nose -notable -note -nothing -notice -novel -now -nuclear -number -nurse -nut -oak -obey -object -oblige -obscure -observe -obtain -obvious -occur -ocean -october -odor -off -offer -office -often -oil -okay -old -olive -olympic -omit -once -one -onion -online -only -open -opera -opinion -oppose -option -orange -orbit -orchard -order -ordinary -organ -orient -original -orphan -ostrich -other -outdoor -outer -output -outside -oval -oven -over -own -owner -oxygen -oyster -ozone -pact -paddle -page -pair -palace -palm -panda -panel -panic -panther -paper -parade -parent -park -parrot -party -pass -patch -path -patient -patrol -pattern -pause -pave -payment -peace -peanut -pear -peasant -pelican -pen -penalty -pencil -people -pepper -perfect -permit -person -pet -phone -photo -phrase -physical -piano -picnic -picture -piece -pig -pigeon -pill -pilot -pink -pioneer -pipe -pistol -pitch -pizza -place -planet -plastic -plate -play -please -pledge -pluck -plug -plunge -poem -poet -point -polar -pole -police -pond -pony -pool -popular -portion -position -possible -post -potato -pottery -poverty -powder -power -practice -praise -predict -prefer -prepare -present -pretty -prevent -price -pride -primary -print -priority -prison -private -prize -problem -process -produce -profit -program -project -promote -proof -property -prosper -protect -proud -provide -public -pudding -pull -pulp -pulse -pumpkin -punch -pupil -puppy -purchase -purity -purpose -purse -push -put -puzzle -pyramid -quality -quantum -quarter -question -quick -quit -quiz -quote -rabbit -raccoon -race -rack -radar -radio -rail -rain -raise -rally -ramp -ranch -random -range -rapid -rare -rate -rather -raven -raw -razor -ready -real -reason -rebel -rebuild -recall -receive -recipe -record -recycle -reduce -reflect -reform -refuse -region -regret -regular -reject -relax -release -relief -rely -remain -remember -remind -remove -render -renew -rent -reopen -repair -repeat -replace -report -require -rescue -resemble -resist -resource -response -result -retire -retreat -return -reunion -reveal -review -reward -rhythm -rib -ribbon -rice -rich -ride -ridge -rifle -right -rigid -ring -riot -ripple -risk -ritual -rival -river -road -roast -robot -robust -rocket -romance -roof -rookie -room -rose -rotate -rough -round -route -royal -rubber -rude -rug -rule -run -runway -rural -sad -saddle -sadness -safe -sail -salad -salmon -salon -salt -salute -same -sample -sand -satisfy -satoshi -sauce -sausage -save -say -scale -scan -scare -scatter -scene -scheme -school -science -scissors -scorpion -scout -scrap -screen -script -scrub -sea -search -season -seat -second -secret -section -security -seed -seek -segment -select -sell -seminar -senior -sense -sentence -series -service -session -settle -setup -seven -shadow -shaft -shallow -share -shed -shell -sheriff -shield -shift -shine -ship -shiver -shock -shoe -shoot -shop -short -shoulder -shove -shrimp -shrug -shuffle -shy -sibling -sick -side -siege -sight -sign -silent -silk -silly -silver -similar -simple -since -sing -siren -sister -situate -six -size -skate -sketch -ski -skill -skin -skirt -skull -slab -slam -sleep -slender -slice -slide -slight -slim -slogan -slot -slow -slush -small -smart -smile -smoke -smooth -snack -snake -snap -sniff -snow -soap -soccer -social -sock -soda -soft -solar -soldier -solid -solution -solve -someone -song -soon -sorry -sort -soul -sound -soup -source -south -space -spare -spatial -spawn -speak -special -speed -spell -spend -sphere -spice -spider -spike -spin -spirit -split -spoil -sponsor -spoon -sport -spot -spray -spread -spring -spy -square -squeeze -squirrel -stable -stadium -staff -stage -stairs -stamp -stand -start -state -stay -steak -steel -stem -step -stereo -stick -still -sting -stock -stomach -stone -stool -story -stove -strategy -street -strike -strong -struggle -student -stuff -stumble -style -subject -submit -subway -success -such -sudden -suffer -sugar -suggest -suit -summer -sun -sunny -sunset -super -supply -supreme -sure -surface -surge -surprise -surround -survey -suspect -sustain -swallow -swamp -swap -swarm -swear -sweet -swift -swim -swing -switch -sword -symbol -symptom -syrup -system -table -tackle -tag -tail -talent -talk -tank -tape -target -task -taste -tattoo -taxi -teach -team -tell -ten -tenant -tennis -tent -term -test -text -thank -that -theme -then -theory -there -they -thing -this -thought -three -thrive -throw -thumb -thunder -ticket -tide -tiger -tilt -timber -time -tiny -tip -tired -tissue -title -toast -tobacco -today -toddler -toe -together -toilet -token -tomato -tomorrow -tone -tongue -tonight -tool -tooth -top -topic -topple -torch -tornado -tortoise -toss -total -tourist -toward -tower -town -toy -track -trade -traffic -tragic -train -transfer -trap -trash -travel -tray -treat -tree -trend -trial -tribe -trick -trigger -trim -trip -trophy -trouble -truck -true -truly -trumpet -trust -truth -try -tube -tuition -tumble -tuna -tunnel -turkey -turn -turtle -twelve -twenty -twice -twin -twist -two -type -typical -ugly -umbrella -unable -unaware -uncle -uncover -under -undo -unfair -unfold -unhappy -uniform -unique -unit -universe -unknown -unlock -until -unusual -unveil -update -upgrade -uphold -upon -upper -upset -urban -urge -usage -use -used -useful -useless -usual -utility -vacant -vacuum -vague -valid -valley -valve -van -vanish -vapor -various -vast -vault -vehicle -velvet -vendor -venture -venue -verb -verify -version -very -vessel -veteran -viable -vibrant -vicious -victory -video -view -village -vintage -violin -virtual -virus -visa -visit -visual -vital -vivid -vocal -voice -void -volcano -volume -vote -voyage -wage -wagon -wait -walk -wall -walnut -want -warfare -warm -warrior -wash -wasp -waste -water -wave -way -wealth -weapon -wear -weasel -weather -web -wedding -weekend -weird -welcome -west -wet -whale -what -wheat -wheel -when -where -whip -whisper -wide -width -wife -wild -will -win -window -wine -wing -wink -winner -winter -wire -wisdom -wise -wish -witness -wolf -woman -wonder -wood -wool -word -work -world -worry -worth -wrap -wreck -wrestle -wrist -write -wrong -yard -year -yellow -you -young -youth -zebra -zero -zone -zoo \ No newline at end of file diff --git a/app/src/main/ic_launcher_bdk-playstore.png b/app/src/main/ic_launcher_bdk-playstore.png deleted file mode 100644 index b834711..0000000 Binary files a/app/src/main/ic_launcher_bdk-playstore.png and /dev/null differ diff --git a/app/src/test/java/org/bitcoindevkit/devkitwallet/ExampleUnitTest.kt b/app/src/test/java/org/bitcoindevkit/devkitwallet/ExampleUnitTest.kt deleted file mode 100644 index 636ec13..0000000 --- a/app/src/test/java/org/bitcoindevkit/devkitwallet/ExampleUnitTest.kt +++ /dev/null @@ -1,11 +0,0 @@ -package org.bitcoindevkit.devkitwallet - -import org.junit.Assert.assertEquals -import org.junit.Test - -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} diff --git a/gradle.properties b/gradle.properties deleted file mode 100644 index 7466277..0000000 --- a/gradle.properties +++ /dev/null @@ -1,6 +0,0 @@ -org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 -android.useAndroidX=true -kotlin.code.style=official -android.enableJetifier=true -android.nonTransitiveRClass=false -android.nonFinalResIds=false diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 7454180..0000000 Binary files a/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 221c4f9..0000000 --- a/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew deleted file mode 100755 index 744e882..0000000 --- a/gradlew +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/env sh - -# -# Copyright 2015 the original author or authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn () { - echo "$*" -} - -die () { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MSYS* | MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=`expr $i + 1` - done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat deleted file mode 100644 index 107acd3..0000000 --- a/gradlew.bat +++ /dev/null @@ -1,89 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/newbuildsystem/jniLibs/arm64-v8a/libjnidispatch.so b/jniLibs/arm64-v8a/libjnidispatch.so similarity index 100% rename from newbuildsystem/jniLibs/arm64-v8a/libjnidispatch.so rename to jniLibs/arm64-v8a/libjnidispatch.so diff --git a/newbuildsystem/jniLibs/x86_64/libjnidispatch.so b/jniLibs/x86_64/libjnidispatch.so similarity index 100% rename from newbuildsystem/jniLibs/x86_64/libjnidispatch.so rename to jniLibs/x86_64/libjnidispatch.so diff --git a/justfile b/justfile index 0a8e9bf..ff919f7 100644 --- a/justfile +++ b/justfile @@ -1,21 +1,19 @@ default: just --list --unsorted -check: - ./gradlew ktlintCheck - -format: - ./gradlew ktlintFormat +# Run the app in an emulator +run: + ./kotlin run # Build the docs website -build-docs: +docs-build: uv run zensical build # Serve the docs locally -serve-docs: +docs-serve: uv run zensical serve -clean-docs: +docs-clean: rm -rf .venv/ rm -rf .cache/ rm -rf site/ diff --git a/newbuildsystem/kotlin b/kotlin similarity index 100% rename from newbuildsystem/kotlin rename to kotlin diff --git a/newbuildsystem/kotlin.bat b/kotlin.bat similarity index 100% rename from newbuildsystem/kotlin.bat rename to kotlin.bat diff --git a/newbuildsystem/module.yaml b/module.yaml similarity index 91% rename from newbuildsystem/module.yaml rename to module.yaml index 0141b6f..728ddb9 100644 --- a/newbuildsystem/module.yaml +++ b/module.yaml @@ -12,8 +12,7 @@ settings: dependencies: - androidx.core:core-ktx:1.17.0 - - androidx.datastore:datastore:1.2.0 - - com.google.protobuf:protobuf-javalite:4.33.5 + - androidx.datastore:datastore:1.2.1 - org.jetbrains.kotlinx:kotlinx-serialization-json:1.10.0 - androidx.core:core-splashscreen:1.2.0 - androidx.activity:activity-compose:1.8.2 @@ -32,5 +31,6 @@ dependencies: # Bitcoin - org.bitcoindevkit:bdk-android:3.0.0 + # QR Codes - com.google.zxing:core:3.5.4 diff --git a/newbuildsystem/.gitignore b/newbuildsystem/.gitignore deleted file mode 100644 index 567609b..0000000 --- a/newbuildsystem/.gitignore +++ /dev/null @@ -1 +0,0 @@ -build/ diff --git a/newbuildsystem/justfile b/newbuildsystem/justfile deleted file mode 100644 index ced6b17..0000000 --- a/newbuildsystem/justfile +++ /dev/null @@ -1,6 +0,0 @@ -default: - just --list --unsorted - -# Run the app in an emulator -run: - ./kotlin run diff --git a/newbuildsystem/res/drawable/bdk_logo.xml b/newbuildsystem/res/drawable/bdk_logo.xml deleted file mode 100644 index a28d65b..0000000 --- a/newbuildsystem/res/drawable/bdk_logo.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - diff --git a/newbuildsystem/res/drawable/bdk_logo2.xml b/newbuildsystem/res/drawable/bdk_logo2.xml deleted file mode 100644 index f8568bd..0000000 --- a/newbuildsystem/res/drawable/bdk_logo2.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - diff --git a/newbuildsystem/res/drawable/ic_launcher_bdk_background.xml b/newbuildsystem/res/drawable/ic_launcher_bdk_background.xml deleted file mode 100644 index 668f371..0000000 --- a/newbuildsystem/res/drawable/ic_launcher_bdk_background.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - diff --git a/newbuildsystem/res/drawable/ic_launcher_bdk_foreground.xml b/newbuildsystem/res/drawable/ic_launcher_bdk_foreground.xml deleted file mode 100644 index 0591aa4..0000000 --- a/newbuildsystem/res/drawable/ic_launcher_bdk_foreground.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - diff --git a/newbuildsystem/res/drawable/ic_launcher_bdk_foreground_no_outline.xml b/newbuildsystem/res/drawable/ic_launcher_bdk_foreground_no_outline.xml deleted file mode 100644 index 0591aa4..0000000 --- a/newbuildsystem/res/drawable/ic_launcher_bdk_foreground_no_outline.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - diff --git a/newbuildsystem/res/font/google_sans_code_light.ttf b/newbuildsystem/res/font/google_sans_code_light.ttf deleted file mode 100644 index 714fb31..0000000 Binary files a/newbuildsystem/res/font/google_sans_code_light.ttf and /dev/null differ diff --git a/newbuildsystem/res/font/inter_bold.ttf b/newbuildsystem/res/font/inter_bold.ttf deleted file mode 100644 index e974d96..0000000 Binary files a/newbuildsystem/res/font/inter_bold.ttf and /dev/null differ diff --git a/newbuildsystem/res/font/inter_medium.ttf b/newbuildsystem/res/font/inter_medium.ttf deleted file mode 100644 index 5c88739..0000000 Binary files a/newbuildsystem/res/font/inter_medium.ttf and /dev/null differ diff --git a/newbuildsystem/res/font/inter_regular.ttf b/newbuildsystem/res/font/inter_regular.ttf deleted file mode 100644 index 6b088a7..0000000 Binary files a/newbuildsystem/res/font/inter_regular.ttf and /dev/null differ diff --git a/newbuildsystem/res/font/inter_thin.ttf b/newbuildsystem/res/font/inter_thin.ttf deleted file mode 100644 index 3505b35..0000000 Binary files a/newbuildsystem/res/font/inter_thin.ttf and /dev/null differ diff --git a/newbuildsystem/res/mipmap-anydpi-v26/ic_launcher.xml b/newbuildsystem/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 2f8431b..0000000 --- a/newbuildsystem/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/newbuildsystem/res/mipmap-anydpi-v26/ic_launcher_bdk.xml b/newbuildsystem/res/mipmap-anydpi-v26/ic_launcher_bdk.xml deleted file mode 100644 index af9e637..0000000 --- a/newbuildsystem/res/mipmap-anydpi-v26/ic_launcher_bdk.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/newbuildsystem/res/mipmap-anydpi-v26/ic_launcher_bdk_round.xml b/newbuildsystem/res/mipmap-anydpi-v26/ic_launcher_bdk_round.xml deleted file mode 100644 index af9e637..0000000 --- a/newbuildsystem/res/mipmap-anydpi-v26/ic_launcher_bdk_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/newbuildsystem/res/mipmap-hdpi/ic_launcher.png b/newbuildsystem/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a571e60..0000000 Binary files a/newbuildsystem/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/newbuildsystem/res/mipmap-hdpi/ic_launcher_bdk.png b/newbuildsystem/res/mipmap-hdpi/ic_launcher_bdk.png deleted file mode 100644 index b94c1ed..0000000 Binary files a/newbuildsystem/res/mipmap-hdpi/ic_launcher_bdk.png and /dev/null differ diff --git a/newbuildsystem/res/mipmap-hdpi/ic_launcher_bdk_round.png b/newbuildsystem/res/mipmap-hdpi/ic_launcher_bdk_round.png deleted file mode 100644 index 07db04c..0000000 Binary files a/newbuildsystem/res/mipmap-hdpi/ic_launcher_bdk_round.png and /dev/null differ diff --git a/newbuildsystem/res/mipmap-hdpi/ic_launcher_round.png b/newbuildsystem/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 61da551..0000000 Binary files a/newbuildsystem/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/newbuildsystem/res/mipmap-mdpi/ic_launcher.png b/newbuildsystem/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index c41dd28..0000000 Binary files a/newbuildsystem/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/newbuildsystem/res/mipmap-mdpi/ic_launcher_bdk.png b/newbuildsystem/res/mipmap-mdpi/ic_launcher_bdk.png deleted file mode 100644 index d4fb078..0000000 Binary files a/newbuildsystem/res/mipmap-mdpi/ic_launcher_bdk.png and /dev/null differ diff --git a/newbuildsystem/res/mipmap-mdpi/ic_launcher_bdk_round.png b/newbuildsystem/res/mipmap-mdpi/ic_launcher_bdk_round.png deleted file mode 100644 index efe9825..0000000 Binary files a/newbuildsystem/res/mipmap-mdpi/ic_launcher_bdk_round.png and /dev/null differ diff --git a/newbuildsystem/res/mipmap-mdpi/ic_launcher_round.png b/newbuildsystem/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index db5080a..0000000 Binary files a/newbuildsystem/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/newbuildsystem/res/mipmap-xhdpi/ic_launcher.png b/newbuildsystem/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 6dba46d..0000000 Binary files a/newbuildsystem/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/newbuildsystem/res/mipmap-xhdpi/ic_launcher_bdk.png b/newbuildsystem/res/mipmap-xhdpi/ic_launcher_bdk.png deleted file mode 100644 index 3bde8f4..0000000 Binary files a/newbuildsystem/res/mipmap-xhdpi/ic_launcher_bdk.png and /dev/null differ diff --git a/newbuildsystem/res/mipmap-xhdpi/ic_launcher_bdk_round.png b/newbuildsystem/res/mipmap-xhdpi/ic_launcher_bdk_round.png deleted file mode 100644 index 5d4b7d9..0000000 Binary files a/newbuildsystem/res/mipmap-xhdpi/ic_launcher_bdk_round.png and /dev/null differ diff --git a/newbuildsystem/res/mipmap-xhdpi/ic_launcher_round.png b/newbuildsystem/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index da31a87..0000000 Binary files a/newbuildsystem/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/newbuildsystem/res/mipmap-xxhdpi/ic_launcher.png b/newbuildsystem/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 15ac681..0000000 Binary files a/newbuildsystem/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/newbuildsystem/res/mipmap-xxhdpi/ic_launcher_bdk.png b/newbuildsystem/res/mipmap-xxhdpi/ic_launcher_bdk.png deleted file mode 100644 index 66f997c..0000000 Binary files a/newbuildsystem/res/mipmap-xxhdpi/ic_launcher_bdk.png and /dev/null differ diff --git a/newbuildsystem/res/mipmap-xxhdpi/ic_launcher_bdk_round.png b/newbuildsystem/res/mipmap-xxhdpi/ic_launcher_bdk_round.png deleted file mode 100644 index ad3ace1..0000000 Binary files a/newbuildsystem/res/mipmap-xxhdpi/ic_launcher_bdk_round.png and /dev/null differ diff --git a/newbuildsystem/res/mipmap-xxhdpi/ic_launcher_round.png b/newbuildsystem/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index b216f2d..0000000 Binary files a/newbuildsystem/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/newbuildsystem/res/mipmap-xxxhdpi/ic_launcher.png b/newbuildsystem/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index f25a419..0000000 Binary files a/newbuildsystem/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/newbuildsystem/res/mipmap-xxxhdpi/ic_launcher_bdk.png b/newbuildsystem/res/mipmap-xxxhdpi/ic_launcher_bdk.png deleted file mode 100644 index 00ab356..0000000 Binary files a/newbuildsystem/res/mipmap-xxxhdpi/ic_launcher_bdk.png and /dev/null differ diff --git a/newbuildsystem/res/mipmap-xxxhdpi/ic_launcher_bdk_round.png b/newbuildsystem/res/mipmap-xxxhdpi/ic_launcher_bdk_round.png deleted file mode 100644 index 28da01a..0000000 Binary files a/newbuildsystem/res/mipmap-xxxhdpi/ic_launcher_bdk_round.png and /dev/null differ diff --git a/newbuildsystem/res/mipmap-xxxhdpi/ic_launcher_round.png b/newbuildsystem/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index e96783c..0000000 Binary files a/newbuildsystem/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/newbuildsystem/res/values/colors.xml b/newbuildsystem/res/values/colors.xml deleted file mode 100644 index f89c5e3..0000000 --- a/newbuildsystem/res/values/colors.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - #1C1B1F - #E6E1E5 - - - - - diff --git a/newbuildsystem/res/values/splash.xml b/newbuildsystem/res/values/splash.xml deleted file mode 100644 index c5adf6c..0000000 --- a/newbuildsystem/res/values/splash.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - diff --git a/newbuildsystem/res/values/strings.xml b/newbuildsystem/res/values/strings.xml deleted file mode 100644 index d0e88cc..0000000 --- a/newbuildsystem/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - Devkit Wallet - diff --git a/newbuildsystem/res/values/themes.xml b/newbuildsystem/res/values/themes.xml deleted file mode 100644 index 11e000d..0000000 --- a/newbuildsystem/res/values/themes.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/newbuildsystem/src/AndroidManifest.xml b/newbuildsystem/src/AndroidManifest.xml deleted file mode 100644 index cbe7c27..0000000 --- a/newbuildsystem/src/AndroidManifest.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/data/Kyoto.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/data/Kyoto.kt deleted file mode 100644 index 9a73ceb..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/data/Kyoto.kt +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.data - -import android.util.Log -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.SharedFlow -import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.launch -import org.bitcoindevkit.CbfBuilder -import org.bitcoindevkit.CbfClient -import org.bitcoindevkit.CbfNode -import org.bitcoindevkit.Info -import org.bitcoindevkit.IpAddress -import org.bitcoindevkit.Network -import org.bitcoindevkit.Peer -import org.bitcoindevkit.ScanType -import org.bitcoindevkit.Transaction -import org.bitcoindevkit.Update -import org.bitcoindevkit.Wallet -import org.bitcoindevkit.Warning -import org.bitcoindevkit.Wtxid -import kotlin.collections.listOf - -private const val TAG = "KyotoClient" - -// TODO: Document this class well -class Kyoto private constructor( - private val kyotoNode: CbfNode, - private val kyotoClient: CbfClient, -) { - private val scope: CoroutineScope = CoroutineScope(Dispatchers.IO) - - fun start(): Flow { - kyotoNode.run() - - return flow { - // Set this to stop under certain circumstances - while (true) { - val update = kyotoClient.update() - emit(update) - } - } - } - - fun infoLog(): SharedFlow { - val sharedFlow = MutableSharedFlow(replay = 0) - scope.launch { - while (true) { - val info = kyotoClient.nextInfo() - sharedFlow.emit(info) - } - } - return sharedFlow - } - - fun warningLog(): SharedFlow { - val sharedFlow = MutableSharedFlow(replay = 0) - scope.launch { - while (true) { - val warning = kyotoClient.nextWarning() - sharedFlow.emit(warning) - } - } - return sharedFlow - } - - fun logToLogcat() { - scope.launch { - infoLog().collect { - Log.i(TAG, it.toString()) - } - } - scope.launch { - warningLog().collect { - Log.i(TAG, it.toString()) - } - } - } - - fun lookupHost(hostname: String): List { - return kyotoClient.lookupHost(hostname) - } - - suspend fun broadcast(transaction: Transaction): Wtxid { - return kyotoClient.broadcast(transaction) - } - - fun connect(peer: Peer) { - kyotoClient.connect(peer) - } - - fun isRunning(): Boolean { - return kyotoClient.isRunning() - } - - fun shutdown() { - kyotoClient.shutdown() - } - - companion object { - private var instance: Kyoto? = null - - fun getInstance(): Kyoto = instance ?: throw KyotoNotInitialized() - - fun create(wallet: Wallet, dataDir: String, network: Network): Kyoto { - Log.i(TAG, "Starting Kyoto node") - val peers: List = when (network) { - Network.REGTEST -> { - val ip: IpAddress = IpAddress.fromIpv4(10u, 0u, 2u, 2u) - val peer1: Peer = Peer(ip, 18444u, false) - listOf(peer1) - } - - Network.SIGNET -> { - val ip: IpAddress = IpAddress.fromIpv4(68u, 47u, 229u, 218u) - val peer1: Peer = Peer(ip, null, false) - listOf(peer1) - } - - else -> { - listOf() - } - } - - val (client, node) = - CbfBuilder() - .dataDir(dataDir) - .peers(peers) - .connections(1u) - .scanType(ScanType.Sync) - .build(wallet) - - return Kyoto(node, client).also { instance = it } - } - } -} - -class KyotoNotInitialized : Exception() diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/data/TxDetails.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/data/TxDetails.kt deleted file mode 100644 index 15036eb..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/data/TxDetails.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.data - -import org.bitcoindevkit.FeeRate -import org.bitcoindevkit.Transaction - -data class TxDetails( - val transaction: Transaction, - val txid: String, - val sent: ULong, - val received: ULong, - val fee: ULong, - val feeRate: FeeRate?, - val pending: Boolean, - val confirmationBlock: ConfirmationBlock?, - val confirmationTimestamp: Timestamp?, -) - -@JvmInline -value class Timestamp(val timestamp: ULong) - -@JvmInline -value class ConfirmationBlock(val height: UInt) diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/data/WalletConfigs.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/data/WalletConfigs.kt deleted file mode 100644 index 8158e41..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/data/WalletConfigs.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.data - -import org.bitcoindevkit.Descriptor -import org.bitcoindevkit.Network -import org.bitcoindevkit.devkitwallet.data.datastore.ActiveWalletScriptType - -data class NewWalletConfig( - val name: String, - val network: Network, - val scriptType: ActiveWalletScriptType, -) - -data class RecoverWalletConfig( - val name: String, - val network: Network, - val scriptType: ActiveWalletScriptType?, - val recoveryPhrase: String?, - val descriptor: Descriptor, - val changeDescriptor: Descriptor, -) diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/data/datastore/AppSettings.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/data/datastore/AppSettings.kt deleted file mode 100644 index 9f62427..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/data/datastore/AppSettings.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.data.datastore - -import androidx.datastore.core.CorruptionException -import androidx.datastore.core.Serializer -import kotlinx.serialization.Serializable -import kotlinx.serialization.SerializationException -import kotlinx.serialization.json.Json -import java.io.InputStream -import java.io.OutputStream - -@Serializable -data class AppSettings( - val darkTheme: Boolean = true, - val introDone: Boolean = false, -) - -object AppSettingsSerializer : Serializer { - override val defaultValue = AppSettings() - - override suspend fun readFrom(input: InputStream): AppSettings { - try { - return Json.decodeFromString(input.readBytes().decodeToString()) - } catch (e: SerializationException) { - throw CorruptionException("Cannot read AppSettings.", e) - } - } - - override suspend fun writeTo(t: AppSettings, output: OutputStream) { - output.write(Json.encodeToString(t).encodeToByteArray()) - } -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/data/datastore/WalletData.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/data/datastore/WalletData.kt deleted file mode 100644 index 760c811..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/data/datastore/WalletData.kt +++ /dev/null @@ -1,57 +0,0 @@ -package org.bitcoindevkit.devkitwallet.data.datastore - -import androidx.datastore.core.CorruptionException -import androidx.datastore.core.Serializer -import kotlinx.serialization.Serializable -import kotlinx.serialization.SerializationException -import kotlinx.serialization.json.Json -import java.io.InputStream -import java.io.OutputStream - -@Serializable -enum class ActiveWalletNetwork { - TESTNET, - SIGNET, - REGTEST, -} - -@Serializable -enum class ActiveWalletScriptType { - P2WPKH, - P2TR, - UNKNOWN, -} - -@Serializable -data class StoredWallet( - val id: String, - val name: String, - val network: ActiveWalletNetwork, - val scriptType: ActiveWalletScriptType, - val descriptor: String, - val changeDescriptor: String, - val recoveryPhrase: String = "", - val fullScanCompleted: Boolean = false, -) - -@Serializable -data class WalletData( - val wallets: List = emptyList(), - // network config fields go here alongside wallets -) - -object WalletDataSerializer : Serializer { - override val defaultValue = WalletData() - - override suspend fun readFrom(input: InputStream): WalletData { - try { - return Json.decodeFromString(input.readBytes().decodeToString()) - } catch (e: SerializationException) { - throw CorruptionException("Cannot read AppSettings.", e) - } - } - - override suspend fun writeTo(t: WalletData, output: OutputStream) { - output.write(Json.encodeToString(t).encodeToByteArray()) - } -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/domain/AppSettingsRepository.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/domain/AppSettingsRepository.kt deleted file mode 100644 index 071708c..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/domain/AppSettingsRepository.kt +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.domain - -import androidx.datastore.core.DataStore -import kotlinx.coroutines.flow.first -import org.bitcoindevkit.devkitwallet.data.datastore.AppSettings - -class AppSettingsRepository(private val store: DataStore) { - suspend fun fetchDarkTheme() = store.data.first().darkTheme - - suspend fun setDarkTheme(isDark: Boolean) = store.updateData { it.copy(darkTheme = isDark) } - - suspend fun fetchIntroDone() = store.data.first().introDone - - suspend fun setIntroDone() = store.updateData { it.copy(introDone = true) } -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/domain/Constants.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/domain/Constants.kt deleted file mode 100644 index 0e7e305..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/domain/Constants.kt +++ /dev/null @@ -1,2067 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.domain - -import org.bitcoindevkit.Network - -val supportedNetworks: List = - listOf( - Network.SIGNET, - Network.TESTNET, - Network.REGTEST, - ) - -val bip39WordList: List = - listOf( - "abandon", - "ability", - "able", - "about", - "above", - "absent", - "absorb", - "abstract", - "absurd", - "abuse", - "access", - "accident", - "account", - "accuse", - "achieve", - "acid", - "acoustic", - "acquire", - "across", - "act", - "action", - "actor", - "actress", - "actual", - "adapt", - "add", - "addict", - "address", - "adjust", - "admit", - "adult", - "advance", - "advice", - "aerobic", - "affair", - "afford", - "afraid", - "again", - "age", - "agent", - "agree", - "ahead", - "aim", - "air", - "airport", - "aisle", - "alarm", - "album", - "alcohol", - "alert", - "alien", - "all", - "alley", - "allow", - "almost", - "alone", - "alpha", - "already", - "also", - "alter", - "always", - "amateur", - "amazing", - "among", - "amount", - "amused", - "analyst", - "anchor", - "ancient", - "anger", - "angle", - "angry", - "animal", - "ankle", - "announce", - "annual", - "another", - "answer", - "antenna", - "antique", - "anxiety", - "any", - "apart", - "apology", - "appear", - "apple", - "approve", - "april", - "arch", - "arctic", - "area", - "arena", - "argue", - "arm", - "armed", - "armor", - "army", - "around", - "arrange", - "arrest", - "arrive", - "arrow", - "art", - "artefact", - "artist", - "artwork", - "ask", - "aspect", - "assault", - "asset", - "assist", - "assume", - "asthma", - "athlete", - "atom", - "attack", - "attend", - "attitude", - "attract", - "auction", - "audit", - "august", - "aunt", - "author", - "auto", - "autumn", - "average", - "avocado", - "avoid", - "awake", - "aware", - "away", - "awesome", - "awful", - "awkward", - "axis", - "baby", - "bachelor", - "bacon", - "badge", - "bag", - "balance", - "balcony", - "ball", - "bamboo", - "banana", - "banner", - "bar", - "barely", - "bargain", - "barrel", - "base", - "basic", - "basket", - "battle", - "beach", - "bean", - "beauty", - "because", - "become", - "beef", - "before", - "begin", - "behave", - "behind", - "believe", - "below", - "belt", - "bench", - "benefit", - "best", - "betray", - "better", - "between", - "beyond", - "bicycle", - "bid", - "bike", - "bind", - "biology", - "bird", - "birth", - "bitter", - "black", - "blade", - "blame", - "blanket", - "blast", - "bleak", - "bless", - "blind", - "blood", - "blossom", - "blouse", - "blue", - "blur", - "blush", - "board", - "boat", - "body", - "boil", - "bomb", - "bone", - "bonus", - "book", - "boost", - "border", - "boring", - "borrow", - "boss", - "bottom", - "bounce", - "box", - "boy", - "bracket", - "brain", - "brand", - "brass", - "brave", - "bread", - "breeze", - "brick", - "bridge", - "brief", - "bright", - "bring", - "brisk", - "broccoli", - "broken", - "bronze", - "broom", - "brother", - "brown", - "brush", - "bubble", - "buddy", - "budget", - "buffalo", - "build", - "bulb", - "bulk", - "bullet", - "bundle", - "bunker", - "burden", - "burger", - "burst", - "bus", - "business", - "busy", - "butter", - "buyer", - "buzz", - "cabbage", - "cabin", - "cable", - "cactus", - "cage", - "cake", - "call", - "calm", - "camera", - "camp", - "can", - "canal", - "cancel", - "candy", - "cannon", - "canoe", - "canvas", - "canyon", - "capable", - "capital", - "captain", - "car", - "carbon", - "card", - "cargo", - "carpet", - "carry", - "cart", - "case", - "cash", - "casino", - "castle", - "casual", - "cat", - "catalog", - "catch", - "category", - "cattle", - "caught", - "cause", - "caution", - "cave", - "ceiling", - "celery", - "cement", - "census", - "century", - "cereal", - "certain", - "chair", - "chalk", - "champion", - "change", - "chaos", - "chapter", - "charge", - "chase", - "chat", - "cheap", - "check", - "cheese", - "chef", - "cherry", - "chest", - "chicken", - "chief", - "child", - "chimney", - "choice", - "choose", - "chronic", - "chuckle", - "chunk", - "churn", - "cigar", - "cinnamon", - "circle", - "citizen", - "city", - "civil", - "claim", - "clap", - "clarify", - "claw", - "clay", - "clean", - "clerk", - "clever", - "click", - "client", - "cliff", - "climb", - "clinic", - "clip", - "clock", - "clog", - "close", - "cloth", - "cloud", - "clown", - "club", - "clump", - "cluster", - "clutch", - "coach", - "coast", - "coconut", - "code", - "coffee", - "coil", - "coin", - "collect", - "color", - "column", - "combine", - "come", - "comfort", - "comic", - "common", - "company", - "concert", - "conduct", - "confirm", - "congress", - "connect", - "consider", - "control", - "convince", - "cook", - "cool", - "copper", - "copy", - "coral", - "core", - "corn", - "correct", - "cost", - "cotton", - "couch", - "country", - "couple", - "course", - "cousin", - "cover", - "coyote", - "crack", - "cradle", - "craft", - "cram", - "crane", - "crash", - "crater", - "crawl", - "crazy", - "cream", - "credit", - "creek", - "crew", - "cricket", - "crime", - "crisp", - "critic", - "crop", - "cross", - "crouch", - "crowd", - "crucial", - "cruel", - "cruise", - "crumble", - "crunch", - "crush", - "cry", - "crystal", - "cube", - "culture", - "cup", - "cupboard", - "curious", - "current", - "curtain", - "curve", - "cushion", - "custom", - "cute", - "cycle", - "dad", - "damage", - "damp", - "dance", - "danger", - "daring", - "dash", - "daughter", - "dawn", - "day", - "deal", - "debate", - "debris", - "decade", - "december", - "decide", - "decline", - "decorate", - "decrease", - "deer", - "defense", - "define", - "defy", - "degree", - "delay", - "deliver", - "demand", - "demise", - "denial", - "dentist", - "deny", - "depart", - "depend", - "deposit", - "depth", - "deputy", - "derive", - "describe", - "desert", - "design", - "desk", - "despair", - "destroy", - "detail", - "detect", - "develop", - "device", - "devote", - "diagram", - "dial", - "diamond", - "diary", - "dice", - "diesel", - "diet", - "differ", - "digital", - "dignity", - "dilemma", - "dinner", - "dinosaur", - "direct", - "dirt", - "disagree", - "discover", - "disease", - "dish", - "dismiss", - "disorder", - "display", - "distance", - "divert", - "divide", - "divorce", - "dizzy", - "doctor", - "document", - "dog", - "doll", - "dolphin", - "domain", - "donate", - "donkey", - "donor", - "door", - "dose", - "double", - "dove", - "draft", - "dragon", - "drama", - "drastic", - "draw", - "dream", - "dress", - "drift", - "drill", - "drink", - "drip", - "drive", - "drop", - "drum", - "dry", - "duck", - "dumb", - "dune", - "during", - "dust", - "dutch", - "duty", - "dwarf", - "dynamic", - "eager", - "eagle", - "early", - "earn", - "earth", - "easily", - "east", - "easy", - "echo", - "ecology", - "economy", - "edge", - "edit", - "educate", - "effort", - "egg", - "eight", - "either", - "elbow", - "elder", - "electric", - "elegant", - "element", - "elephant", - "elevator", - "elite", - "else", - "embark", - "embody", - "embrace", - "emerge", - "emotion", - "employ", - "empower", - "empty", - "enable", - "enact", - "end", - "endless", - "endorse", - "enemy", - "energy", - "enforce", - "engage", - "engine", - "enhance", - "enjoy", - "enlist", - "enough", - "enrich", - "enroll", - "ensure", - "enter", - "entire", - "entry", - "envelope", - "episode", - "equal", - "equip", - "era", - "erase", - "erode", - "erosion", - "error", - "erupt", - "escape", - "essay", - "essence", - "estate", - "eternal", - "ethics", - "evidence", - "evil", - "evoke", - "evolve", - "exact", - "example", - "excess", - "exchange", - "excite", - "exclude", - "excuse", - "execute", - "exercise", - "exhaust", - "exhibit", - "exile", - "exist", - "exit", - "exotic", - "expand", - "expect", - "expire", - "explain", - "expose", - "express", - "extend", - "extra", - "eye", - "eyebrow", - "fabric", - "face", - "faculty", - "fade", - "faint", - "faith", - "fall", - "false", - "fame", - "family", - "famous", - "fan", - "fancy", - "fantasy", - "farm", - "fashion", - "fat", - "fatal", - "father", - "fatigue", - "fault", - "favorite", - "feature", - "february", - "federal", - "fee", - "feed", - "feel", - "female", - "fence", - "festival", - "fetch", - "fever", - "few", - "fiber", - "fiction", - "field", - "figure", - "file", - "film", - "filter", - "final", - "find", - "fine", - "finger", - "finish", - "fire", - "firm", - "first", - "fiscal", - "fish", - "fit", - "fitness", - "fix", - "flag", - "flame", - "flash", - "flat", - "flavor", - "flee", - "flight", - "flip", - "float", - "flock", - "floor", - "flower", - "fluid", - "flush", - "fly", - "foam", - "focus", - "fog", - "foil", - "fold", - "follow", - "food", - "foot", - "force", - "forest", - "forget", - "fork", - "fortune", - "forum", - "forward", - "fossil", - "foster", - "found", - "fox", - "fragile", - "frame", - "frequent", - "fresh", - "friend", - "fringe", - "frog", - "front", - "frost", - "frown", - "frozen", - "fruit", - "fuel", - "fun", - "funny", - "furnace", - "fury", - "future", - "gadget", - "gain", - "galaxy", - "gallery", - "game", - "gap", - "garage", - "garbage", - "garden", - "garlic", - "garment", - "gas", - "gasp", - "gate", - "gather", - "gauge", - "gaze", - "general", - "genius", - "genre", - "gentle", - "genuine", - "gesture", - "ghost", - "giant", - "gift", - "giggle", - "ginger", - "giraffe", - "girl", - "give", - "glad", - "glance", - "glare", - "glass", - "glide", - "glimpse", - "globe", - "gloom", - "glory", - "glove", - "glow", - "glue", - "goat", - "goddess", - "gold", - "good", - "goose", - "gorilla", - "gospel", - "gossip", - "govern", - "gown", - "grab", - "grace", - "grain", - "grant", - "grape", - "grass", - "gravity", - "great", - "green", - "grid", - "grief", - "grit", - "grocery", - "group", - "grow", - "grunt", - "guard", - "guess", - "guide", - "guilt", - "guitar", - "gun", - "gym", - "habit", - "hair", - "half", - "hammer", - "hamster", - "hand", - "happy", - "harbor", - "hard", - "harsh", - "harvest", - "hat", - "have", - "hawk", - "hazard", - "head", - "health", - "heart", - "heavy", - "hedgehog", - "height", - "hello", - "helmet", - "help", - "hen", - "hero", - "hidden", - "high", - "hill", - "hint", - "hip", - "hire", - "history", - "hobby", - "hockey", - "hold", - "hole", - "holiday", - "hollow", - "home", - "honey", - "hood", - "hope", - "horn", - "horror", - "horse", - "hospital", - "host", - "hotel", - "hour", - "hover", - "hub", - "huge", - "human", - "humble", - "humor", - "hundred", - "hungry", - "hunt", - "hurdle", - "hurry", - "hurt", - "husband", - "hybrid", - "ice", - "icon", - "idea", - "identify", - "idle", - "ignore", - "ill", - "illegal", - "illness", - "image", - "imitate", - "immense", - "immune", - "impact", - "impose", - "improve", - "impulse", - "inch", - "include", - "income", - "increase", - "index", - "indicate", - "indoor", - "industry", - "infant", - "inflict", - "inform", - "inhale", - "inherit", - "initial", - "inject", - "injury", - "inmate", - "inner", - "innocent", - "input", - "inquiry", - "insane", - "insect", - "inside", - "inspire", - "install", - "intact", - "interest", - "into", - "invest", - "invite", - "involve", - "iron", - "island", - "isolate", - "issue", - "item", - "ivory", - "jacket", - "jaguar", - "jar", - "jazz", - "jealous", - "jeans", - "jelly", - "jewel", - "job", - "join", - "joke", - "journey", - "joy", - "judge", - "juice", - "jump", - "jungle", - "junior", - "junk", - "just", - "kangaroo", - "keen", - "keep", - "ketchup", - "key", - "kick", - "kid", - "kidney", - "kind", - "kingdom", - "kiss", - "kit", - "kitchen", - "kite", - "kitten", - "kiwi", - "knee", - "knife", - "knock", - "know", - "lab", - "label", - "labor", - "ladder", - "lady", - "lake", - "lamp", - "language", - "laptop", - "large", - "later", - "latin", - "laugh", - "laundry", - "lava", - "law", - "lawn", - "lawsuit", - "layer", - "lazy", - "leader", - "leaf", - "learn", - "leave", - "lecture", - "left", - "leg", - "legal", - "legend", - "leisure", - "lemon", - "lend", - "length", - "lens", - "leopard", - "lesson", - "letter", - "level", - "liar", - "liberty", - "library", - "license", - "life", - "lift", - "light", - "like", - "limb", - "limit", - "link", - "lion", - "liquid", - "list", - "little", - "live", - "lizard", - "load", - "loan", - "lobster", - "local", - "lock", - "logic", - "lonely", - "long", - "loop", - "lottery", - "loud", - "lounge", - "love", - "loyal", - "lucky", - "luggage", - "lumber", - "lunar", - "lunch", - "luxury", - "lyrics", - "machine", - "mad", - "magic", - "magnet", - "maid", - "mail", - "main", - "major", - "make", - "mammal", - "man", - "manage", - "mandate", - "mango", - "mansion", - "manual", - "maple", - "marble", - "march", - "margin", - "marine", - "market", - "marriage", - "mask", - "mass", - "master", - "match", - "material", - "math", - "matrix", - "matter", - "maximum", - "maze", - "meadow", - "mean", - "measure", - "meat", - "mechanic", - "medal", - "media", - "melody", - "melt", - "member", - "memory", - "mention", - "menu", - "mercy", - "merge", - "merit", - "merry", - "mesh", - "message", - "metal", - "method", - "middle", - "midnight", - "milk", - "million", - "mimic", - "mind", - "minimum", - "minor", - "minute", - "miracle", - "mirror", - "misery", - "miss", - "mistake", - "mix", - "mixed", - "mixture", - "mobile", - "model", - "modify", - "mom", - "moment", - "monitor", - "monkey", - "monster", - "month", - "moon", - "moral", - "more", - "morning", - "mosquito", - "mother", - "motion", - "motor", - "mountain", - "mouse", - "move", - "movie", - "much", - "muffin", - "mule", - "multiply", - "muscle", - "museum", - "mushroom", - "music", - "must", - "mutual", - "myself", - "mystery", - "myth", - "naive", - "name", - "napkin", - "narrow", - "nasty", - "nation", - "nature", - "near", - "neck", - "need", - "negative", - "neglect", - "neither", - "nephew", - "nerve", - "nest", - "net", - "network", - "neutral", - "never", - "news", - "next", - "nice", - "night", - "noble", - "noise", - "nominee", - "noodle", - "normal", - "north", - "nose", - "notable", - "note", - "nothing", - "notice", - "novel", - "now", - "nuclear", - "number", - "nurse", - "nut", - "oak", - "obey", - "object", - "oblige", - "obscure", - "observe", - "obtain", - "obvious", - "occur", - "ocean", - "october", - "odor", - "off", - "offer", - "office", - "often", - "oil", - "okay", - "old", - "olive", - "olympic", - "omit", - "once", - "one", - "onion", - "online", - "only", - "open", - "opera", - "opinion", - "oppose", - "option", - "orange", - "orbit", - "orchard", - "order", - "ordinary", - "organ", - "orient", - "original", - "orphan", - "ostrich", - "other", - "outdoor", - "outer", - "output", - "outside", - "oval", - "oven", - "over", - "own", - "owner", - "oxygen", - "oyster", - "ozone", - "pact", - "paddle", - "page", - "pair", - "palace", - "palm", - "panda", - "panel", - "panic", - "panther", - "paper", - "parade", - "parent", - "park", - "parrot", - "party", - "pass", - "patch", - "path", - "patient", - "patrol", - "pattern", - "pause", - "pave", - "payment", - "peace", - "peanut", - "pear", - "peasant", - "pelican", - "pen", - "penalty", - "pencil", - "people", - "pepper", - "perfect", - "permit", - "person", - "pet", - "phone", - "photo", - "phrase", - "physical", - "piano", - "picnic", - "picture", - "piece", - "pig", - "pigeon", - "pill", - "pilot", - "pink", - "pioneer", - "pipe", - "pistol", - "pitch", - "pizza", - "place", - "planet", - "plastic", - "plate", - "play", - "please", - "pledge", - "pluck", - "plug", - "plunge", - "poem", - "poet", - "point", - "polar", - "pole", - "police", - "pond", - "pony", - "pool", - "popular", - "portion", - "position", - "possible", - "post", - "potato", - "pottery", - "poverty", - "powder", - "power", - "practice", - "praise", - "predict", - "prefer", - "prepare", - "present", - "pretty", - "prevent", - "price", - "pride", - "primary", - "print", - "priority", - "prison", - "private", - "prize", - "problem", - "process", - "produce", - "profit", - "program", - "project", - "promote", - "proof", - "property", - "prosper", - "protect", - "proud", - "provide", - "public", - "pudding", - "pull", - "pulp", - "pulse", - "pumpkin", - "punch", - "pupil", - "puppy", - "purchase", - "purity", - "purpose", - "purse", - "push", - "put", - "puzzle", - "pyramid", - "quality", - "quantum", - "quarter", - "question", - "quick", - "quit", - "quiz", - "quote", - "rabbit", - "raccoon", - "race", - "rack", - "radar", - "radio", - "rail", - "rain", - "raise", - "rally", - "ramp", - "ranch", - "random", - "range", - "rapid", - "rare", - "rate", - "rather", - "raven", - "raw", - "razor", - "ready", - "real", - "reason", - "rebel", - "rebuild", - "recall", - "receive", - "recipe", - "record", - "recycle", - "reduce", - "reflect", - "reform", - "refuse", - "region", - "regret", - "regular", - "reject", - "relax", - "release", - "relief", - "rely", - "remain", - "remember", - "remind", - "remove", - "render", - "renew", - "rent", - "reopen", - "repair", - "repeat", - "replace", - "report", - "require", - "rescue", - "resemble", - "resist", - "resource", - "response", - "result", - "retire", - "retreat", - "return", - "reunion", - "reveal", - "review", - "reward", - "rhythm", - "rib", - "ribbon", - "rice", - "rich", - "ride", - "ridge", - "rifle", - "right", - "rigid", - "ring", - "riot", - "ripple", - "risk", - "ritual", - "rival", - "river", - "road", - "roast", - "robot", - "robust", - "rocket", - "romance", - "roof", - "rookie", - "room", - "rose", - "rotate", - "rough", - "round", - "route", - "royal", - "rubber", - "rude", - "rug", - "rule", - "run", - "runway", - "rural", - "sad", - "saddle", - "sadness", - "safe", - "sail", - "salad", - "salmon", - "salon", - "salt", - "salute", - "same", - "sample", - "sand", - "satisfy", - "satoshi", - "sauce", - "sausage", - "save", - "say", - "scale", - "scan", - "scare", - "scatter", - "scene", - "scheme", - "school", - "science", - "scissors", - "scorpion", - "scout", - "scrap", - "screen", - "script", - "scrub", - "sea", - "search", - "season", - "seat", - "second", - "secret", - "section", - "security", - "seed", - "seek", - "segment", - "select", - "sell", - "seminar", - "senior", - "sense", - "sentence", - "series", - "service", - "session", - "settle", - "setup", - "seven", - "shadow", - "shaft", - "shallow", - "share", - "shed", - "shell", - "sheriff", - "shield", - "shift", - "shine", - "ship", - "shiver", - "shock", - "shoe", - "shoot", - "shop", - "short", - "shoulder", - "shove", - "shrimp", - "shrug", - "shuffle", - "shy", - "sibling", - "sick", - "side", - "siege", - "sight", - "sign", - "silent", - "silk", - "silly", - "silver", - "similar", - "simple", - "since", - "sing", - "siren", - "sister", - "situate", - "six", - "size", - "skate", - "sketch", - "ski", - "skill", - "skin", - "skirt", - "skull", - "slab", - "slam", - "sleep", - "slender", - "slice", - "slide", - "slight", - "slim", - "slogan", - "slot", - "slow", - "slush", - "small", - "smart", - "smile", - "smoke", - "smooth", - "snack", - "snake", - "snap", - "sniff", - "snow", - "soap", - "soccer", - "social", - "sock", - "soda", - "soft", - "solar", - "soldier", - "solid", - "solution", - "solve", - "someone", - "song", - "soon", - "sorry", - "sort", - "soul", - "sound", - "soup", - "source", - "south", - "space", - "spare", - "spatial", - "spawn", - "speak", - "special", - "speed", - "spell", - "spend", - "sphere", - "spice", - "spider", - "spike", - "spin", - "spirit", - "split", - "spoil", - "sponsor", - "spoon", - "sport", - "spot", - "spray", - "spread", - "spring", - "spy", - "square", - "squeeze", - "squirrel", - "stable", - "stadium", - "staff", - "stage", - "stairs", - "stamp", - "stand", - "start", - "state", - "stay", - "steak", - "steel", - "stem", - "step", - "stereo", - "stick", - "still", - "sting", - "stock", - "stomach", - "stone", - "stool", - "story", - "stove", - "strategy", - "street", - "strike", - "strong", - "struggle", - "student", - "stuff", - "stumble", - "style", - "subject", - "submit", - "subway", - "success", - "such", - "sudden", - "suffer", - "sugar", - "suggest", - "suit", - "summer", - "sun", - "sunny", - "sunset", - "super", - "supply", - "supreme", - "sure", - "surface", - "surge", - "surprise", - "surround", - "survey", - "suspect", - "sustain", - "swallow", - "swamp", - "swap", - "swarm", - "swear", - "sweet", - "swift", - "swim", - "swing", - "switch", - "sword", - "symbol", - "symptom", - "syrup", - "system", - "table", - "tackle", - "tag", - "tail", - "talent", - "talk", - "tank", - "tape", - "target", - "task", - "taste", - "tattoo", - "taxi", - "teach", - "team", - "tell", - "ten", - "tenant", - "tennis", - "tent", - "term", - "test", - "text", - "thank", - "that", - "theme", - "then", - "theory", - "there", - "they", - "thing", - "this", - "thought", - "three", - "thrive", - "throw", - "thumb", - "thunder", - "ticket", - "tide", - "tiger", - "tilt", - "timber", - "time", - "tiny", - "tip", - "tired", - "tissue", - "title", - "toast", - "tobacco", - "today", - "toddler", - "toe", - "together", - "toilet", - "token", - "tomato", - "tomorrow", - "tone", - "tongue", - "tonight", - "tool", - "tooth", - "top", - "topic", - "topple", - "torch", - "tornado", - "tortoise", - "toss", - "total", - "tourist", - "toward", - "tower", - "town", - "toy", - "track", - "trade", - "traffic", - "tragic", - "train", - "transfer", - "trap", - "trash", - "travel", - "tray", - "treat", - "tree", - "trend", - "trial", - "tribe", - "trick", - "trigger", - "trim", - "trip", - "trophy", - "trouble", - "truck", - "true", - "truly", - "trumpet", - "trust", - "truth", - "try", - "tube", - "tuition", - "tumble", - "tuna", - "tunnel", - "turkey", - "turn", - "turtle", - "twelve", - "twenty", - "twice", - "twin", - "twist", - "two", - "type", - "typical", - "ugly", - "umbrella", - "unable", - "unaware", - "uncle", - "uncover", - "under", - "undo", - "unfair", - "unfold", - "unhappy", - "uniform", - "unique", - "unit", - "universe", - "unknown", - "unlock", - "until", - "unusual", - "unveil", - "update", - "upgrade", - "uphold", - "upon", - "upper", - "upset", - "urban", - "urge", - "usage", - "use", - "used", - "useful", - "useless", - "usual", - "utility", - "vacant", - "vacuum", - "vague", - "valid", - "valley", - "valve", - "van", - "vanish", - "vapor", - "various", - "vast", - "vault", - "vehicle", - "velvet", - "vendor", - "venture", - "venue", - "verb", - "verify", - "version", - "very", - "vessel", - "veteran", - "viable", - "vibrant", - "vicious", - "victory", - "video", - "view", - "village", - "vintage", - "violin", - "virtual", - "virus", - "visa", - "visit", - "visual", - "vital", - "vivid", - "vocal", - "voice", - "void", - "volcano", - "volume", - "vote", - "voyage", - "wage", - "wagon", - "wait", - "walk", - "wall", - "walnut", - "want", - "warfare", - "warm", - "warrior", - "wash", - "wasp", - "waste", - "water", - "wave", - "way", - "wealth", - "weapon", - "wear", - "weasel", - "weather", - "web", - "wedding", - "weekend", - "weird", - "welcome", - "west", - "wet", - "whale", - "what", - "wheat", - "wheel", - "when", - "where", - "whip", - "whisper", - "wide", - "width", - "wife", - "wild", - "will", - "win", - "window", - "wine", - "wing", - "wink", - "winner", - "winter", - "wire", - "wisdom", - "wise", - "wish", - "witness", - "wolf", - "woman", - "wonder", - "wood", - "wool", - "word", - "work", - "world", - "worry", - "worth", - "wrap", - "wreck", - "wrestle", - "wrist", - "write", - "wrong", - "yard", - "year", - "yellow", - "you", - "young", - "youth", - "zebra", - "zero", - "zone", - "zoo", - ) diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/domain/CurrencyUnit.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/domain/CurrencyUnit.kt deleted file mode 100644 index e33b463..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/domain/CurrencyUnit.kt +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.domain - -enum class CurrencyUnit { - Bitcoin, - Satoshi, -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/domain/DwLogger.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/domain/DwLogger.kt deleted file mode 100644 index 293fff0..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/domain/DwLogger.kt +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.domain - -import java.time.Instant -import java.time.ZoneId -import java.time.temporal.ChronoUnit - -object DwLogger { - private const val MAX_LOGS = 5000 - private val logEntries = ArrayDeque(MAX_LOGS) - private val lock = Any() - - fun log(tag: LogLevel, message: String) { - synchronized(lock) { - if (logEntries.size >= MAX_LOGS) { - logEntries.removeLast() - } - val millis = System.currentTimeMillis() - val dateTime = - Instant - .ofEpochMilli(millis) - .atZone(ZoneId.systemDefault()) - .toLocalDateTime() - .truncatedTo(ChronoUnit.SECONDS) - - logEntries.addFirst("$dateTime $tag $message") - } - } - - fun getLogs(): List { - synchronized(lock) { - return logEntries.toList() - } - } - - enum class LogLevel { - INFO, - WARN, - ERROR, - ; - - override fun toString(): String { - return when (this) { - INFO -> "[INFO] " - WARN -> "[WARN] " - ERROR -> "[ERROR]" - } - } - } -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/domain/Wallet.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/domain/Wallet.kt deleted file mode 100644 index 29fd725..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/domain/Wallet.kt +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.domain - -import android.util.Log -import kotlinx.coroutines.runBlocking -import org.bitcoindevkit.Address -import org.bitcoindevkit.AddressInfo -import org.bitcoindevkit.Amount -import org.bitcoindevkit.CanonicalTx -import org.bitcoindevkit.ChainPosition -import org.bitcoindevkit.Descriptor -import org.bitcoindevkit.DescriptorSecretKey -import org.bitcoindevkit.FeeRate -import org.bitcoindevkit.KeychainKind -import org.bitcoindevkit.Mnemonic -import org.bitcoindevkit.Network -import org.bitcoindevkit.NetworkKind -import org.bitcoindevkit.Persister -import org.bitcoindevkit.Psbt -import org.bitcoindevkit.Script -import org.bitcoindevkit.TxBuilder -import org.bitcoindevkit.Update -import org.bitcoindevkit.WordCount -import org.bitcoindevkit.devkitwallet.data.ConfirmationBlock -import org.bitcoindevkit.devkitwallet.data.NewWalletConfig -import org.bitcoindevkit.devkitwallet.data.RecoverWalletConfig -import org.bitcoindevkit.devkitwallet.data.Timestamp -import org.bitcoindevkit.devkitwallet.data.TxDetails -import org.bitcoindevkit.devkitwallet.data.datastore.ActiveWalletScriptType -import org.bitcoindevkit.devkitwallet.data.datastore.StoredWallet -import org.bitcoindevkit.devkitwallet.domain.utils.intoDomain -import org.bitcoindevkit.devkitwallet.domain.utils.intoProto -import org.bitcoindevkit.devkitwallet.presentation.viewmodels.mvi.Recipient -import java.util.UUID -import org.bitcoindevkit.Wallet as BdkWallet - -private const val TAG = "Wallet" - -class Wallet private constructor( - val wallet: BdkWallet, - private val walletSecrets: WalletSecrets, - private val connection: Persister, - private var fullScanCompleted: Boolean, - private val walletId: String, - private val walletRepository: WalletRepository, - val internalAppFilesPath: String, - val network: Network, -) { - fun getWalletSecrets(): WalletSecrets { - return walletSecrets - } - - fun bestBlock(): UInt { - return wallet.latestCheckpoint().height - } - - fun createTransaction(recipientList: List, feeRate: FeeRate, opReturnMsg: String?): Psbt { - // technique 1 for adding a list of recipients to the TxBuilder - // var txBuilder = TxBuilder() - // for (recipient in recipientList) { - // txBuilder = txBuilder.addRecipient(address = recipient.first, amount = recipient.second) - // } - // txBuilder = txBuilder.feeRate(satPerVbyte = fee_rate) - - // technique 2 for adding a list of recipients to the TxBuilder - var txBuilder = - recipientList.fold(TxBuilder()) { builder, recipient -> - // val address = Address(recipient.address) - val scriptPubKey: Script = Address(recipient.address, this.network).scriptPubkey() - builder.addRecipient(scriptPubKey, Amount.fromSat(recipient.amount)) - } - // if (!opReturnMsg.isNullOrEmpty()) { - // txBuilder = txBuilder.addData(opReturnMsg.toByteArray(charset = Charsets.UTF_8).asUByteArray().toList()) - // } - return txBuilder.feeRate(feeRate).finish(wallet) - } - - // @OptIn(ExperimentalUnsignedTypes::class) - // fun createSendAllTransaction( - // recipient: String, - // feeRate: Float, - // enableRBF: Boolean, - // opReturnMsg: String? - // ): PartiallySignedTransaction { - // val scriptPubkey: Script = Address(recipient).scriptPubkey() - // var txBuilder = TxBuilder() - // .drainWallet() - // .drainTo(scriptPubkey) - // .feeRate(satPerVbyte = feeRate) - // - // if (enableRBF) { - // txBuilder = txBuilder.enableRbf() - // } - // if (!opReturnMsg.isNullOrEmpty()) { - // txBuilder = txBuilder.addData(opReturnMsg.toByteArray(charset = Charsets.UTF_8).asUByteArray().toList()) - // } - // return txBuilder.finish(wallet).psbt - // } - - // fun createBumpFeeTransaction(txid: String, feeRate: Float): PartiallySignedTransaction { - // return BumpFeeTxBuilder(txid = txid, newFeeRate = feeRate) - // .enableRbf() - // .finish(wallet = wallet) - // } - - fun sign(psbt: Psbt): Boolean { - return wallet.sign(psbt) - } - - // fun broadcast(signedPsbt: Psbt): String { - // currentBlockchainClient?.broadcast(signedPsbt.extractTx()) - // ?: throw IllegalStateException("Blockchain client not initialized") - // return signedPsbt.extractTx().computeTxid().toString() - // } - - private fun getAllTransactions(): List = wallet.transactions() - - fun getAllTxDetails(): List { - val transactions = getAllTransactions() - return transactions.map { tx -> - val txid = tx.transaction.computeTxid() - val (sent, received) = wallet.sentAndReceived(tx.transaction) - var feeRate: FeeRate? = null - var fee: Amount? = null - // TODO: I don't know why we're getting negative fees here, but it looks like a bug - try { - fee = wallet.calculateFee(tx.transaction) - } catch (e: Exception) { - Log.e(TAG, "Error calculating fee rate for tx $txid: $e") - } - try { - feeRate = wallet.calculateFeeRate(tx.transaction) - } catch (e: Exception) { - Log.e(TAG, "Error calculating fee for tx $txid: $e") - } - - val (confirmationBlock, confirmationTimestamp, pending) = - when (val position = tx.chainPosition) { - is ChainPosition.Unconfirmed -> { - Triple(null, null, true) - } - - is ChainPosition.Confirmed -> { - Triple( - ConfirmationBlock(position.confirmationBlockTime.blockId.height), - Timestamp(position.confirmationBlockTime.confirmationTime), - false, - ) - } - } - TxDetails( - tx.transaction, - txid.toString(), - sent.toSat(), - received.toSat(), - fee?.toSat() ?: 0uL, - feeRate, - pending, - confirmationBlock, - confirmationTimestamp - ) - } - } - - // fun getTransaction(txid: String): TransactionDetails? { - // val allTransactions = getAllTransactions() - // allTransactions.forEach { - // if (it.txid == txid) { - // return it - // } - // } - // return null - // } - - fun getBalance(): ULong = wallet.balance().total.toSat() - - fun getNewAddress(): AddressInfo = wallet.revealNextAddress(KeychainKind.EXTERNAL) - - fun applyUpdate(update: Update) { - wallet.applyUpdate(update) - wallet.persist(connection) - Log.i("KYOTOTEST", "Wallet applied a Kyoto update") - } - - companion object { - fun createWallet( - newWalletConfig: NewWalletConfig, - internalAppFilesPath: String, - walletRepository: WalletRepository, - ): Wallet { - val mnemonic = Mnemonic(WordCount.WORDS12) - val bip32ExtendedRootKey = DescriptorSecretKey(NetworkKind.TEST, mnemonic, null) - val descriptor: Descriptor = - createScriptAppropriateDescriptor( - newWalletConfig.scriptType, - bip32ExtendedRootKey, - KeychainKind.EXTERNAL, - ) - val changeDescriptor: Descriptor = - createScriptAppropriateDescriptor( - newWalletConfig.scriptType, - bip32ExtendedRootKey, - KeychainKind.INTERNAL, - ) - val walletId = UUID.randomUUID().toString() - val connection = Persister.newSqlite("$internalAppFilesPath/wallet-${walletId.take(8)}.sqlite3") - - // Create SingleWallet object for saving to datastore - val newWalletForDatastore: StoredWallet = - StoredWallet( - id = walletId, - name = newWalletConfig.name, - network = newWalletConfig.network.intoProto(), - scriptType = ActiveWalletScriptType.P2WPKH, - descriptor = descriptor.toStringWithSecret(), - changeDescriptor = changeDescriptor.toStringWithSecret(), - recoveryPhrase = mnemonic.toString() - ) - // TODO: launch this correctly, not on the main thread - // Save the new wallet to the datastore - runBlocking { walletRepository.addWallet(newWalletForDatastore) } - - val bdkWallet = - BdkWallet( - descriptor = descriptor, - changeDescriptor = changeDescriptor, - network = newWalletConfig.network, - persister = connection, - ) - - val walletSecrets = WalletSecrets(descriptor, changeDescriptor, mnemonic.toString()) - - return Wallet( - wallet = bdkWallet, - walletSecrets = walletSecrets, - connection = connection, - fullScanCompleted = false, - walletId = walletId, - walletRepository = walletRepository, - internalAppFilesPath = internalAppFilesPath, - network = newWalletConfig.network - ) - } - - fun loadActiveWallet( - activeWallet: StoredWallet, - internalAppFilesPath: String, - walletRepository: WalletRepository, - ): Wallet { - val descriptor = Descriptor(activeWallet.descriptor, NetworkKind.TEST) - val changeDescriptor = Descriptor(activeWallet.changeDescriptor, NetworkKind.TEST) - val connection = Persister.newSqlite("$internalAppFilesPath/wallet-${activeWallet.id.take(8)}.sqlite3") - val bdkWallet = - BdkWallet.load( - descriptor = descriptor, - changeDescriptor = changeDescriptor, - persister = connection, - ) - - val walletSecrets = WalletSecrets(descriptor, changeDescriptor, activeWallet.recoveryPhrase) - return Wallet( - wallet = bdkWallet, - walletSecrets = walletSecrets, - connection = connection, - fullScanCompleted = activeWallet.fullScanCompleted, - walletId = activeWallet.id, - walletRepository = walletRepository, - internalAppFilesPath = internalAppFilesPath, - network = activeWallet.network.intoDomain() - ) - } - - fun recoverWallet( - recoverWalletConfig: RecoverWalletConfig, - internalAppFilesPath: String, - walletRepository: WalletRepository, - ): Wallet { - Log.i(TAG, "Recovering wallet with config: $recoverWalletConfig") - var descriptor: Descriptor? = null - var changeDescriptor: Descriptor? = null - var mnemonicString: String = "" - - // If there is a recovery phrase, we use it to recover the wallet - if (recoverWalletConfig.recoveryPhrase != null && recoverWalletConfig.scriptType != null) { - val mnemonic: Mnemonic = Mnemonic.fromString(recoverWalletConfig.recoveryPhrase) - mnemonicString = mnemonic.toString() - val bip32ExtendedRootKey = DescriptorSecretKey(NetworkKind.TEST, mnemonic, null) - descriptor = - createScriptAppropriateDescriptor( - recoverWalletConfig.scriptType, - bip32ExtendedRootKey, - KeychainKind.EXTERNAL, - ) - changeDescriptor = - createScriptAppropriateDescriptor( - recoverWalletConfig.scriptType, - bip32ExtendedRootKey, - KeychainKind.INTERNAL, - ) - } else { - descriptor = recoverWalletConfig.descriptor - changeDescriptor = recoverWalletConfig.changeDescriptor - } - val walletId = UUID.randomUUID().toString() - val connection = Persister.newSqlite("$internalAppFilesPath/wallet-${walletId.take(8)}.sqlite3") - - // Create SingleWallet object for saving to datastore - val newWalletForDatastore: StoredWallet = - StoredWallet( - id = walletId, - name = recoverWalletConfig.name, - network = recoverWalletConfig.network.intoProto(), - scriptType = ActiveWalletScriptType.P2WPKH, - descriptor = descriptor.toStringWithSecret(), - changeDescriptor = changeDescriptor.toStringWithSecret(), - recoveryPhrase = mnemonicString - ) - - // TODO: launch this correctly, not on the main thread - // Save the new wallet to the datastore - runBlocking { walletRepository.addWallet(newWalletForDatastore) } - - val bdkWallet = - BdkWallet( - descriptor = descriptor, - changeDescriptor = changeDescriptor, - persister = connection, - network = recoverWalletConfig.network, - ) - - val walletSecrets = WalletSecrets(descriptor, changeDescriptor, mnemonicString) - return Wallet( - wallet = bdkWallet, - walletSecrets = walletSecrets, - connection = connection, - fullScanCompleted = false, - walletId = walletId, - walletRepository = walletRepository, - internalAppFilesPath = internalAppFilesPath, - network = recoverWalletConfig.network - ) - } - } -} - -fun createScriptAppropriateDescriptor( - scriptType: ActiveWalletScriptType, - bip32ExtendedRootKey: DescriptorSecretKey, - keychain: KeychainKind, -): Descriptor { - return when (scriptType) { - ActiveWalletScriptType.P2WPKH -> Descriptor.newBip84(bip32ExtendedRootKey, keychain, NetworkKind.TEST) - ActiveWalletScriptType.P2TR -> Descriptor.newBip86(bip32ExtendedRootKey, keychain, NetworkKind.TEST) - ActiveWalletScriptType.UNKNOWN -> TODO() - // ActiveWalletScriptType.UNRECOGNIZED -> TODO() - } -} - -data class WalletSecrets( - val descriptor: Descriptor, - val changeDescriptor: Descriptor, - val recoveryPhrase: String, -) diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/domain/WalletRepository.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/domain/WalletRepository.kt deleted file mode 100644 index 8c9e204..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/domain/WalletRepository.kt +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.domain - -import androidx.datastore.core.DataStore -import kotlinx.coroutines.flow.first -import org.bitcoindevkit.devkitwallet.data.datastore.StoredWallet -import org.bitcoindevkit.devkitwallet.data.datastore.WalletData - -class WalletRepository(private val store: DataStore) { - suspend fun fetchWallets() = store.data.first().wallets - - suspend fun addWallet(wallet: StoredWallet) = store.updateData { it.copy(wallets = it.wallets + wallet) } - - suspend fun setFullScanCompleted(walletId: String) = - store.updateData { data -> - data.copy( - wallets = data.wallets.map { - if (it.id == walletId) it.copy(fullScanCompleted = true) else it - } - ) - } -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/domain/utils/FormatInBtc.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/domain/utils/FormatInBtc.kt deleted file mode 100644 index e8b5974..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/domain/utils/FormatInBtc.kt +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.domain.utils - -import java.text.DecimalFormat - -fun ULong?.formatInBtc(): String { - val balanceInSats = - if (this == 0UL || this == null) { - 0F - } else { - this.toDouble().div(100_000_000) - } - return DecimalFormat("0.00000000").format(balanceInSats) -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/domain/utils/ProtobufExtensions.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/domain/utils/ProtobufExtensions.kt deleted file mode 100644 index d8d505b..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/domain/utils/ProtobufExtensions.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.domain.utils - -import org.bitcoindevkit.Network -import org.bitcoindevkit.devkitwallet.data.datastore.ActiveWalletNetwork - -fun Network.intoProto(): ActiveWalletNetwork { - return when (this) { - Network.TESTNET -> ActiveWalletNetwork.TESTNET - Network.TESTNET4 -> throw IllegalArgumentException("Bitcoin testnet 4 network is not supported") - Network.SIGNET -> ActiveWalletNetwork.SIGNET - Network.REGTEST -> ActiveWalletNetwork.REGTEST - Network.BITCOIN -> throw IllegalArgumentException("Bitcoin mainnet network is not supported") - } -} - -fun ActiveWalletNetwork.intoDomain(): Network { - return when (this) { - ActiveWalletNetwork.TESTNET -> Network.TESTNET - ActiveWalletNetwork.SIGNET -> Network.SIGNET - ActiveWalletNetwork.REGTEST -> Network.REGTEST - // ActiveWalletNetwork.UNRECOGNIZED -> throw IllegalArgumentException("Unrecognized network") - } -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/domain/utils/Timestamps.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/domain/utils/Timestamps.kt deleted file mode 100644 index efb850d..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/domain/utils/Timestamps.kt +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.domain.utils - -import android.text.format.DateFormat -import java.util.Calendar -import java.util.Locale - -// extension function on the ULong timestamp provided in the Transaction.Confirmed type -fun ULong.timestampToString(): String { - val calendar = Calendar.getInstance(Locale.ENGLISH) - calendar.timeInMillis = (this * 1000u).toLong() - return DateFormat.format("MMMM d yyyy HH:mm", calendar).toString() -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/DevkitWalletActivity.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/DevkitWalletActivity.kt deleted file mode 100644 index b064ded..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/DevkitWalletActivity.kt +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation - -import android.content.Context -import android.graphics.drawable.ColorDrawable -import android.os.Bundle -import android.util.Log -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue -import androidx.core.graphics.drawable.toDrawable -import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen -import androidx.datastore.core.DataStore -import androidx.datastore.dataStore -import androidx.lifecycle.lifecycleScope -import kotlinx.coroutines.async -import kotlinx.coroutines.launch -import org.bitcoindevkit.devkitwallet.data.NewWalletConfig -import org.bitcoindevkit.devkitwallet.data.RecoverWalletConfig -import org.bitcoindevkit.devkitwallet.data.datastore.AppSettings -import org.bitcoindevkit.devkitwallet.data.datastore.AppSettingsSerializer -import org.bitcoindevkit.devkitwallet.data.datastore.StoredWallet -import org.bitcoindevkit.devkitwallet.data.datastore.WalletData -import org.bitcoindevkit.devkitwallet.data.datastore.WalletDataSerializer -import org.bitcoindevkit.devkitwallet.domain.AppSettingsRepository -import org.bitcoindevkit.devkitwallet.domain.DwLogger -import org.bitcoindevkit.devkitwallet.domain.DwLogger.LogLevel.INFO -import org.bitcoindevkit.devkitwallet.domain.Wallet -import org.bitcoindevkit.devkitwallet.domain.WalletRepository -import org.bitcoindevkit.devkitwallet.presentation.navigation.AppNavigation -import org.bitcoindevkit.devkitwallet.presentation.theme.DevkitTheme -import org.bitcoindevkit.devkitwallet.presentation.theme.themeSurfaceColor -import org.bitcoindevkit.devkitwallet.presentation.ui.screens.intro.OnboardingScreen - -private const val TAG = "DevkitWalletActivity" -private val Context.appSettingsStore: DataStore by dataStore( - fileName = "app_settings.json", - serializer = AppSettingsSerializer, -) -private val Context.walletDataStore: DataStore by dataStore( - fileName = "wallet_data.json", - serializer = WalletDataSerializer, -) - -class DevkitWalletActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - installSplashScreen() - - super.onCreate(savedInstanceState) - - // Initialize Devkit Wallet Logger (used in the LogsScreen) - DwLogger.log(INFO, "Devkit Wallet app started") - - val appSettingsRepository = AppSettingsRepository(appSettingsStore) - val walletRepository = WalletRepository(walletDataStore) - - var activeWallet: Wallet? by mutableStateOf(null) - var activeWallets: List by mutableStateOf(emptyList()) - var onboardingDone: Boolean by mutableStateOf(false) - var useDarkTheme: Boolean by mutableStateOf(true) - var preferencesLoaded: Boolean by mutableStateOf(false) - - val onBuildWalletButtonClicked: (WalletCreateType) -> Unit = { walletCreateType -> - try { - activeWallet = - when (walletCreateType) { - is WalletCreateType.FROMSCRATCH -> { - Wallet.createWallet( - newWalletConfig = walletCreateType.newWalletConfig, - internalAppFilesPath = filesDir.absolutePath, - walletRepository = walletRepository, - ) - } - - is WalletCreateType.LOADEXISTING -> { - Wallet.loadActiveWallet( - activeWallet = walletCreateType.activeWallet, - internalAppFilesPath = filesDir.absolutePath, - walletRepository = walletRepository, - ) - } - - is WalletCreateType.RECOVER -> { - Wallet.recoverWallet( - recoverWalletConfig = walletCreateType.recoverWalletConfig, - internalAppFilesPath = filesDir.absolutePath, - walletRepository = walletRepository, - ) - } - } - } catch (e: Throwable) { - Log.i(TAG, "Could not build wallet: $e") - } - } - - val onToggleTheme: () -> Unit = { - useDarkTheme = !useDarkTheme - // Keep the window background in sync with the Compose theme. Navigation transitions - // include a fade-out, which causes the window background to show through briefly. - // Updating it here (synchronously, before Compose recomposes) prevents a color flash. - window.setBackgroundDrawable(themeSurfaceColor(useDarkTheme).toDrawable()) - lifecycleScope.launch { appSettingsRepository.setDarkTheme(useDarkTheme) } - } - - lifecycleScope.launch { - activeWallets = - async { - walletRepository.fetchWallets() - }.await() - - onboardingDone = - async { - appSettingsRepository.fetchIntroDone() - }.await() - - useDarkTheme = - async { - appSettingsRepository.fetchDarkTheme() - }.await() - - // Set the window background before allowing the UI to render for the first time, - // so the correct surface color is already in place when Compose draws its first frame. - window.setBackgroundDrawable(ColorDrawable(themeSurfaceColor(useDarkTheme))) - preferencesLoaded = true - } - - val onFinishOnboarding: () -> Unit = { - lifecycleScope.launch { appSettingsRepository.setIntroDone() } - onboardingDone = true - } - - setContent { - if (!preferencesLoaded) return@setContent - - if (!onboardingDone) { - DwLogger.log(INFO, "First time opening the app, triggering onboarding screen") - OnboardingScreen(onFinishOnboarding) - } else { - DevkitTheme(darkTheme = useDarkTheme) { - AppNavigation( - activeWallet = activeWallet, - activeWallets = activeWallets, - onBuildWalletButtonClicked = onBuildWalletButtonClicked, - useDarkTheme = useDarkTheme, - onToggleTheme = onToggleTheme, - ) - } - } - } - } -} - -sealed class WalletCreateType { - data class FROMSCRATCH(val newWalletConfig: NewWalletConfig) : WalletCreateType() - - data class LOADEXISTING(val activeWallet: StoredWallet) : WalletCreateType() - - data class RECOVER(val recoverWalletConfig: RecoverWalletConfig) : WalletCreateType() -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/navigation/AppNavigation.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/navigation/AppNavigation.kt deleted file mode 100644 index 48b1364..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/navigation/AppNavigation.kt +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.navigation - -import androidx.compose.animation.EnterTransition -import androidx.compose.animation.ExitTransition -import androidx.compose.animation.core.CubicBezierEasing -import androidx.compose.animation.core.tween -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut -import androidx.compose.animation.slideInHorizontally -import androidx.compose.animation.slideOutHorizontally -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.remember -import androidx.navigation.NavHostController -import androidx.navigation.compose.NavHost -import androidx.navigation.compose.composable -import androidx.navigation.compose.rememberNavController -import androidx.navigation.toRoute -import org.bitcoindevkit.devkitwallet.data.datastore.StoredWallet -import org.bitcoindevkit.devkitwallet.domain.Wallet -import org.bitcoindevkit.devkitwallet.presentation.WalletCreateType -import org.bitcoindevkit.devkitwallet.presentation.ui.screens.intro.ActiveWalletsScreen -import org.bitcoindevkit.devkitwallet.presentation.ui.screens.intro.CreateNewWalletScreen -import org.bitcoindevkit.devkitwallet.presentation.ui.screens.intro.RecoverWalletScreen -import org.bitcoindevkit.devkitwallet.presentation.ui.screens.intro.WalletChoiceScreen -import org.bitcoindevkit.devkitwallet.presentation.ui.screens.settings.AboutScreen -import org.bitcoindevkit.devkitwallet.presentation.ui.screens.settings.BlockchainClientScreen -import org.bitcoindevkit.devkitwallet.presentation.ui.screens.settings.LogsScreen -import org.bitcoindevkit.devkitwallet.presentation.ui.screens.settings.RecoveryDataScreen -import org.bitcoindevkit.devkitwallet.presentation.ui.screens.settings.SettingsScreen -import org.bitcoindevkit.devkitwallet.presentation.ui.screens.settings.ThemeScreen -import org.bitcoindevkit.devkitwallet.presentation.ui.screens.wallet.RBFScreen -import org.bitcoindevkit.devkitwallet.presentation.ui.screens.wallet.ReceiveScreen -import org.bitcoindevkit.devkitwallet.presentation.ui.screens.wallet.SendScreen -import org.bitcoindevkit.devkitwallet.presentation.ui.screens.wallet.TransactionHistoryScreen -import org.bitcoindevkit.devkitwallet.presentation.ui.screens.wallet.TransactionScreen -import org.bitcoindevkit.devkitwallet.presentation.ui.screens.wallet.WalletHomeScreen -import org.bitcoindevkit.devkitwallet.presentation.viewmodels.AddressViewModel -import org.bitcoindevkit.devkitwallet.presentation.viewmodels.SendViewModel -import org.bitcoindevkit.devkitwallet.presentation.viewmodels.WalletViewModel - -// M3 motion easing curves -private val EmphasizedDecelerate = CubicBezierEasing(0.05f, 0.7f, 0.1f, 1.0f) -private val EmphasizedAccelerate = CubicBezierEasing(0.3f, 0.0f, 0.8f, 0.15f) - -private const val ENTER_DURATION = 400 -private const val EXIT_DURATION = 200 -private const val FADE_IN_DURATION = 300 -private const val FADE_OUT_DURATION = 150 -private const val SLIDE_DISTANCE_DP = 30 - -// Forward: entering screen slides in from right and fades in (decelerate) -private val m3ForwardEnter: EnterTransition = - slideInHorizontally( - animationSpec = tween(ENTER_DURATION, easing = EmphasizedDecelerate), - initialOffsetX = { SLIDE_DISTANCE_DP * 3 }, - ) + fadeIn( - animationSpec = tween(FADE_IN_DURATION, delayMillis = 50, easing = EmphasizedDecelerate), - ) - -// Forward: outgoing screen slides out to left and fades out (accelerate) -private val m3ForwardExit: ExitTransition = - slideOutHorizontally( - animationSpec = tween(EXIT_DURATION, easing = EmphasizedAccelerate), - targetOffsetX = { -SLIDE_DISTANCE_DP * 3 }, - ) + fadeOut( - animationSpec = tween(FADE_OUT_DURATION, easing = EmphasizedAccelerate), - ) - -// Backward: returning screen slides in from left and fades in (decelerate) -private val m3BackwardEnter: EnterTransition = - slideInHorizontally( - animationSpec = tween(ENTER_DURATION, easing = EmphasizedDecelerate), - initialOffsetX = { -SLIDE_DISTANCE_DP * 3 }, - ) + fadeIn( - animationSpec = tween(FADE_IN_DURATION, delayMillis = 50, easing = EmphasizedDecelerate), - ) - -// Backward: outgoing screen slides out to right and fades out (accelerate) -private val m3BackwardExit: ExitTransition = - slideOutHorizontally( - animationSpec = tween(EXIT_DURATION, easing = EmphasizedAccelerate), - targetOffsetX = { SLIDE_DISTANCE_DP * 3 }, - ) + fadeOut( - animationSpec = tween(FADE_OUT_DURATION, easing = EmphasizedAccelerate), - ) - -@Composable -fun AppNavigation( - activeWallet: Wallet?, - activeWallets: List, - onBuildWalletButtonClicked: (WalletCreateType) -> Unit, - useDarkTheme: Boolean, - onToggleTheme: () -> Unit, -) { - val navController: NavHostController = rememberNavController() - - val walletViewModel = remember(activeWallet) { activeWallet?.let { WalletViewModel(it) } } - val addressViewModel = remember(activeWallet) { activeWallet?.let { AddressViewModel(it) } } - val sendViewModel = remember(activeWallet) { activeWallet?.let { SendViewModel(it) } } - - LaunchedEffect(activeWallet) { - if (activeWallet != null) { - navController.navigate(HomeScreen) { - popUpTo(WalletChoiceScreen) { inclusive = true } - } - } - } - - NavHost( - navController = navController, - startDestination = WalletChoiceScreen, - enterTransition = { m3ForwardEnter }, - exitTransition = { m3ForwardExit }, - popEnterTransition = { m3BackwardEnter }, - popExitTransition = { m3BackwardExit }, - ) { - // Create-wallet flow destinations - composable { - WalletChoiceScreen(navController = navController) - } - - composable { - ActiveWalletsScreen( - activeWallets = activeWallets, - navController = navController, - onBuildWalletButtonClicked - ) - } - - composable { - CreateNewWalletScreen(navController = navController, onBuildWalletButtonClicked) - } - - composable { - RecoverWalletScreen(onAction = onBuildWalletButtonClicked, navController = navController) - } - - // Wallet screens - composable { - WalletHomeScreen( - state = walletViewModel!!.state, - onAction = walletViewModel::onAction, - navController = navController, - ) - } - - composable { - ReceiveScreen( - state = addressViewModel!!.state, - onAction = addressViewModel::onAction, - navController = navController, - ) - } - - composable { SendScreen(navController, sendViewModel!!) } - - composable { - val args = it.toRoute() - RBFScreen(args.txid, navController) - } - - composable { TransactionHistoryScreen(navController, activeWallet!!) } - - composable { - val args = it.toRoute() - TransactionScreen(args.txid, navController) - } - - // Settings/drawer screens - composable { SettingsScreen(navController = navController) } - - composable { AboutScreen(navController = navController) } - - composable { - RecoveryDataScreen(activeWallet!!.getWalletSecrets(), navController = navController) - } - - composable { - BlockchainClientScreen( - state = walletViewModel!!.state, - onAction = walletViewModel::onAction, - navController = navController, - ) - } - - composable { LogsScreen(navController = navController) } - - composable { - ThemeScreen( - useDarkTheme = useDarkTheme, - onToggleTheme = onToggleTheme, - navController = navController, - ) - } - } -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/navigation/Destinations.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/navigation/Destinations.kt deleted file mode 100644 index 917f863..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/navigation/Destinations.kt +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.navigation - -import kotlinx.serialization.Serializable - -// Create wallet navigation destinations -@Serializable -object WalletChoiceScreen - -@Serializable -object ActiveWalletsScreen - -@Serializable -object CreateNewWalletScreen - -@Serializable -object WalletRecoveryScreen - -// Home navigation destinations -@Serializable -object SettingsScreen - -@Serializable -object AboutScreen - -@Serializable -object RecoveryPhraseScreen - -@Serializable -object BlockchainClientScreen - -@Serializable -object LogsScreen - -@Serializable -object ThemeScreen - -// Wallet navigation destinations -@Serializable -object HomeScreen - -@Serializable -object ReceiveScreen - -@Serializable -object SendScreen - -@Serializable -object TransactionHistoryScreen - -@Serializable -data class TransactionScreen(val txid: String) - -@Serializable -data class RbfScreen(val txid: String) diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/theme/DevkitWalletColors.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/theme/DevkitWalletColors.kt deleted file mode 100644 index d1662b4..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/theme/DevkitWalletColors.kt +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.theme - -import androidx.compose.ui.graphics.Color - -// NightGlow (dark theme) accent colors -val NightGlowHistoryAccent: Color = Color(0xFFE3D082) -val NightGlowSubtle: Color = Color(0xFF79747E) - -// DayGlow (light theme) accent colors -val DayGlowHistoryAccent: Color = Color(0xFF816C2A) -val DayGlowSubtle: Color = Color(0xFF79747E) diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/theme/Fonts.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/theme/Fonts.kt deleted file mode 100644 index c1843ba..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/theme/Fonts.kt +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.theme - -import androidx.compose.ui.text.font.Font -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.font.FontStyle -import androidx.compose.ui.text.font.FontWeight -import org.bitcoindevkit.devkitwallet.R - -// val monoRegular = -// FontFamily( -// Font( -// resId = R.font.ia_writer_mono_regular, -// weight = FontWeight.Normal, -// style = FontStyle.Normal, -// ), -// ) -// -// val monoBold = -// FontFamily( -// Font( -// resId = R.font.ia_writer_mono_bold, -// weight = FontWeight.Bold, -// style = FontStyle.Normal, -// ), -// ) - -val googleSansCode = - FontFamily( - Font( - resId = R.font.google_sans_code_light, - weight = FontWeight.Light, - style = FontStyle.Normal, - ), - ) - -val inter = - FontFamily( - Font( - resId = R.font.inter_thin, - weight = FontWeight.Thin, - style = FontStyle.Normal, - ), - Font( - resId = R.font.inter_regular, - weight = FontWeight.Normal, - style = FontStyle.Normal, - ), - Font( - resId = R.font.inter_medium, - weight = FontWeight.Medium, - style = FontStyle.Normal, - ), - Font( - resId = R.font.inter_bold, - weight = FontWeight.Bold, - style = FontStyle.Normal, - ), - ) diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/theme/Theme.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/theme/Theme.kt deleted file mode 100644 index f2e9f60..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/theme/Theme.kt +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.theme - -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.darkColorScheme -import androidx.compose.material3.lightColorScheme -import androidx.compose.runtime.Composable -import androidx.compose.ui.graphics.Color - -private val NightGlowColorScheme = darkColorScheme( - surface = Color(0xFF1C1B1F), - onSurface = Color(0xFFE6E1E5), - surfaceVariant = Color(0xFF49454F), - onSurfaceVariant = Color(0xFFCAC4D0), - background = Color(0xFF1C1B1F), - onBackground = Color(0xFFE6E1E5), - outline = Color(0xFFCAC4D0), - outlineVariant = Color(0xFF49454F), - primary = Color(0xFFF2D2B6), - onPrimary = Color(0xFF1C1B1F), - secondary = Color(0xFFC6B2E0), - onSecondary = Color(0xFF1C1B1F), - tertiary = Color(0xFF8FD998), - onTertiary = Color(0xFF1C1B1F), -) - -private val DayGlowColorScheme = lightColorScheme( - surface = Color(0xFFFFF8F4), - onSurface = Color(0xFF1C1B1F), - surfaceVariant = Color(0xFFEDE5DF), - onSurfaceVariant = Color(0xFF49454F), - background = Color(0xFFFFF8F4), - onBackground = Color(0xFF1C1B1F), - outline = Color(0xFF79747E), - outlineVariant = Color(0xFFCAC4D0), - primary = Color(0xFF7D5260), - onPrimary = Color(0xFFFFFFFF), - secondary = Color(0xFF625B71), - onSecondary = Color(0xFFFFFFFF), - tertiary = Color(0xFF2E6A3C), - onTertiary = Color(0xFFFFFFFF), -) - -// Returns the surface color for the given theme as an ARGB int for use outside of Compose (e.g. -// setting the window background from the Activity). Keeps the values co-located with the color -// schemes above so there is a single source of truth for each theme's surface color. -fun themeSurfaceColor(darkTheme: Boolean): Int = if (darkTheme) 0xFF1C1B1F.toInt() else 0xFFFFF8F4.toInt() - -@Composable -fun DevkitTheme(darkTheme: Boolean = true, content: @Composable () -> Unit) { - MaterialTheme( - colorScheme = if (darkTheme) NightGlowColorScheme else DayGlowColorScheme, - typography = devkitTypography, - content = content, - ) -} - -// NOTES ON THE UI -// - The standard padding is 32dp for start/end, 16dp for top/bottom diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/theme/Type.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/theme/Type.kt deleted file mode 100644 index b18f25e..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/theme/Type.kt +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.theme - -import androidx.compose.material3.Typography -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.sp - -internal val devkitTypography = - Typography( - labelLarge = - TextStyle( - fontFamily = inter, - fontWeight = FontWeight.Normal, - fontSize = 16.sp, - lineHeight = 28.sp, - ), - ) diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/CustomSnackbar.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/CustomSnackbar.kt deleted file mode 100644 index 8f98067..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/CustomSnackbar.kt +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.ui.components - -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Snackbar -import androidx.compose.material3.SnackbarData -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import com.composables.icons.lucide.Lucide -import com.composables.icons.lucide.X -import org.bitcoindevkit.devkitwallet.presentation.theme.inter - -@Composable -fun CustomSnackbar(data: SnackbarData) { - val colorScheme = MaterialTheme.colorScheme - Snackbar( - modifier = Modifier.padding(12.dp), - action = { - IconButton( - onClick = { data.performAction() }, - ) { - Icon( - imageVector = Lucide.X, - contentDescription = "Ok", - tint = colorScheme.onSurface, - ) - } - }, - containerColor = colorScheme.surfaceVariant, - ) { - Text( - text = data.visuals.message, - fontFamily = inter, - fontSize = 14.sp, - color = colorScheme.onSurface, - ) - } -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/LoadingAnimation.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/LoadingAnimation.kt deleted file mode 100644 index 50fc018..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/LoadingAnimation.kt +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.ui.components - -import androidx.compose.animation.core.Animatable -import androidx.compose.animation.core.RepeatMode -import androidx.compose.animation.core.infiniteRepeatable -import androidx.compose.animation.core.tween -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.remember -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.dp -import kotlinx.coroutines.delay - -@Composable -fun LoadingAnimation( - circleColor: Color = Color(0xffE9C46A), - circleSize: Dp = 21.dp, - animationDelay: Int = 800, - initialAlpha: Float = 0.3f, -) { - val circles = - listOf( - remember { Animatable(initialValue = initialAlpha) }, - remember { Animatable(initialValue = initialAlpha) }, - remember { Animatable(initialValue = initialAlpha) }, - ) - - circles.forEachIndexed { index, animatable -> - LaunchedEffect(Unit) { - // Use coroutine delay to sync animations - delay(timeMillis = (animationDelay / circles.size).toLong() * index) - - animatable.animateTo( - targetValue = 1f, - animationSpec = - infiniteRepeatable( - animation = - tween( - durationMillis = animationDelay, - ), - repeatMode = RepeatMode.Reverse, - ), - ) - } - } - - // container for circles - Row { - circles.forEachIndexed { index, animatable -> - // gap between the circles - if (index != 0) Spacer(modifier = Modifier.width(width = 6.dp)) - - Box( - modifier = - Modifier - .size(size = circleSize) - .clip(shape = CircleShape) - .background(circleColor.copy(alpha = animatable.value)), - ) - } - } -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/NeutralButton.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/NeutralButton.kt deleted file mode 100644 index f44b605..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/NeutralButton.kt +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.ui.components - -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import org.bitcoindevkit.devkitwallet.presentation.theme.inter - -@Composable -fun NeutralButton(text: String, enabled: Boolean, modifier: Modifier? = null, onClick: () -> Unit) { - val colorScheme = MaterialTheme.colorScheme - Button( - onClick = onClick, - colors = - ButtonDefaults.buttonColors( - containerColor = colorScheme.secondary, - disabledContainerColor = colorScheme.secondary.copy(alpha = 0.4f), - ), - shape = RoundedCornerShape(16.dp), - enabled = enabled, - modifier = - modifier ?: Modifier - .height(60.dp) - .fillMaxWidth(0.9f) - .padding(vertical = 4.dp, horizontal = 8.dp), - ) { - Text( - text = text, - fontFamily = inter, - ) - } -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/RadioButtonWithLabel.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/RadioButtonWithLabel.kt deleted file mode 100644 index 9a702da..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/RadioButtonWithLabel.kt +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.ui.components - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.selection.selectable -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.RadioButton -import androidx.compose.material3.RadioButtonDefaults -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import org.bitcoindevkit.devkitwallet.presentation.theme.inter - -@Composable -fun RadioButtonWithLabel(label: String, isSelected: Boolean, onSelect: () -> Unit) { - val colorScheme = MaterialTheme.colorScheme - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(4.dp), - modifier = - Modifier - .padding(0.dp) - .selectable( - selected = isSelected, - onClick = onSelect, - ), - ) { - RadioButton( - selected = isSelected, - onClick = onSelect, - colors = - RadioButtonDefaults.colors( - selectedColor = colorScheme.primary, - unselectedColor = colorScheme.outline, - ), - modifier = - Modifier - .padding(start = 8.dp) - .size(40.dp), - ) - Text( - text = label, - color = colorScheme.onSurface, - fontFamily = inter, - fontSize = 12.sp, - modifier = - Modifier - .clickable(onClick = onSelect) - .padding(0.dp), - ) - } -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/SecondaryScreensAppBar.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/SecondaryScreensAppBar.kt deleted file mode 100644 index f572c5b..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/SecondaryScreensAppBar.kt +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.ui.components - -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.rounded.ArrowBack -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.material3.TopAppBar -import androidx.compose.material3.TopAppBarDefaults -import androidx.compose.runtime.Composable -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.sp -import org.bitcoindevkit.devkitwallet.presentation.theme.inter - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -internal fun SecondaryScreensAppBar(title: String, navigation: () -> Unit) { - val colorScheme = MaterialTheme.colorScheme - TopAppBar( - title = { - Text( - text = title, - color = colorScheme.onSurface, - fontSize = 18.sp, - fontFamily = inter, - fontWeight = FontWeight.Medium, - ) - }, - navigationIcon = { - IconButton(onClick = navigation) { - Icon( - imageVector = Icons.AutoMirrored.Rounded.ArrowBack, - contentDescription = "Back", - tint = colorScheme.onSurface, - ) - } - }, - colors = TopAppBarDefaults.topAppBarColors( - containerColor = colorScheme.surface, - ), - ) -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/TransactionCards.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/TransactionCards.kt deleted file mode 100644 index f2b04b1..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/TransactionCards.kt +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.ui.components - -import android.util.Log -import androidx.compose.foundation.background -import androidx.compose.foundation.border -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.navigation.NavController -import org.bitcoindevkit.devkitwallet.data.TxDetails -import org.bitcoindevkit.devkitwallet.domain.utils.timestampToString -import org.bitcoindevkit.devkitwallet.presentation.theme.DayGlowHistoryAccent -import org.bitcoindevkit.devkitwallet.presentation.theme.inter -import org.bitcoindevkit.devkitwallet.presentation.ui.screens.wallet.viewTransaction - -private const val TAG = "TransactionCards" - -@Composable -fun ConfirmedTransactionCard(details: TxDetails, navController: NavController) { - val colorScheme = MaterialTheme.colorScheme - Row( - Modifier - .padding(horizontal = 8.dp, vertical = 6.dp) - .fillMaxWidth() - .background( - color = colorScheme.surfaceVariant.copy(alpha = 0.5f), - shape = RoundedCornerShape(16.dp), - ).border( - width = 1.dp, - color = colorScheme.outline.copy(alpha = 0.08f), - shape = RoundedCornerShape(16.dp), - ).clickable { viewTransaction(navController = navController, txid = details.txid) }, - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.Absolute.SpaceBetween, - ) { - Text( - confirmedTransactionsItem(details), - fontFamily = inter, - fontSize = 12.sp, - lineHeight = 20.sp, - color = colorScheme.onSurface, - modifier = Modifier.padding(16.dp), - ) - Box( - modifier = - Modifier - .padding(top = 16.dp, end = 16.dp) - .size(24.dp) - .clip(shape = CircleShape) - .background(colorScheme.tertiary.copy(alpha = 0.6f)) - .align(Alignment.Top), - ) - } -} - -@Composable -fun PendingTransactionCard(details: TxDetails, navController: NavController) { - val colorScheme = MaterialTheme.colorScheme - Row( - Modifier - .padding(horizontal = 8.dp, vertical = 6.dp) - .fillMaxWidth() - .background( - color = colorScheme.surfaceVariant.copy(alpha = 0.5f), - shape = RoundedCornerShape(16.dp), - ).border( - width = 1.5.dp, - color = DayGlowHistoryAccent.copy(alpha = 0.5f), - shape = RoundedCornerShape(16.dp), - ).clickable { - viewTransaction( - navController = navController, - txid = details.txid, - ) - }, - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.Absolute.SpaceBetween, - ) { - Text( - pendingTransactionsItem(details), - fontFamily = inter, - fontSize = 12.sp, - color = colorScheme.onSurface, - modifier = Modifier.padding(16.dp), - ) - Box( - modifier = - Modifier - .padding(top = 16.dp, end = 16.dp) - .size(24.dp) - .clip(shape = CircleShape) - .background(DayGlowHistoryAccent.copy(alpha = 0.6f)) - .align(Alignment.Top), - ) - } -} - -fun pendingTransactionsItem(txDetails: TxDetails): String { - return buildString { - Log.i(TAG, "Pending transaction list item: $txDetails") - - appendLine("Confirmation time: Pending") - appendLine("Received: ${txDetails.received}") - appendLine("Sent: ${txDetails.sent}") - appendLine("Total fee: ${txDetails.fee} sat") - appendLine("Fee rate: ${txDetails.feeRate?.toSatPerVbCeil() ?: 0} sat/vbyte") - append("Txid: ${txDetails.txid.take(n = 8)}...${txDetails.txid.takeLast(n = 8)}") - } -} - -fun confirmedTransactionsItem(txDetails: TxDetails): String { - return buildString { - Log.i(TAG, "Transaction list item: $txDetails") - - appendLine("Confirmation time: ${txDetails.confirmationTimestamp?.timestamp?.timestampToString()}") - appendLine("Received: ${txDetails.received} sat") - appendLine("Sent: ${txDetails.sent} sat") - appendLine("Total fee: ${txDetails.fee} sat") - appendLine("Fee rate: ${txDetails.feeRate?.toSatPerVbCeil() ?: 0} sat/vbyte") - appendLine("Block: ${txDetails.confirmationBlock?.height}") - append("Txid: ${txDetails.txid.take(n = 8)}...${txDetails.txid.takeLast(n = 8)}") - } -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/WalletOptionsCard.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/WalletOptionsCard.kt deleted file mode 100644 index b5d5c41..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/WalletOptionsCard.kt +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.ui.components - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import org.bitcoindevkit.Network -import org.bitcoindevkit.devkitwallet.data.datastore.ActiveWalletScriptType -import org.bitcoindevkit.devkitwallet.domain.supportedNetworks -import org.bitcoindevkit.devkitwallet.presentation.theme.inter -import org.bitcoindevkit.devkitwallet.presentation.ui.screens.intro.displayString - -@Composable -fun WalletOptionsCard( - scriptTypes: List, - selectedNetwork: MutableState, - selectedScriptType: MutableState, -) { - val colorScheme = MaterialTheme.colorScheme - Column( - Modifier - .fillMaxWidth() - .background( - color = colorScheme.surfaceVariant, - shape = RoundedCornerShape(16.dp), - ), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.Start, - ) { - Text( - text = "Network", - fontFamily = inter, - fontSize = 14.sp, - color = colorScheme.onSurface, - modifier = - Modifier - .align(Alignment.CenterHorizontally) - .padding(top = 8.dp, bottom = 8.dp), - ) - - HorizontalDivider( - color = colorScheme.outline.copy(alpha = 0.15f), - thickness = 1.dp, - modifier = Modifier.padding(bottom = 8.dp), - ) - - supportedNetworks.forEachIndexed { index, it -> - RadioButtonWithLabel( - label = it.displayString(), - isSelected = selectedNetwork.value == it, - onSelect = { selectedNetwork.value = it }, - ) - if (index == 2) Spacer(modifier = Modifier.padding(bottom = 8.dp)) - } - - Text( - text = "Script Type", - fontFamily = inter, - fontSize = 14.sp, - color = colorScheme.onSurface, - modifier = - Modifier - .align(Alignment.CenterHorizontally) - .padding(top = 16.dp, bottom = 8.dp), - ) - - HorizontalDivider( - color = colorScheme.outline.copy(alpha = 0.15f), - thickness = 1.dp, - modifier = Modifier.padding(bottom = 8.dp), - ) - - scriptTypes.forEachIndexed { index, it -> - RadioButtonWithLabel( - label = it.displayString(), - isSelected = selectedScriptType.value == it, - onSelect = { selectedScriptType.value = it }, - ) - if (index == 1) Spacer(modifier = Modifier.padding(bottom = 8.dp)) - } - } -} - -@Composable -fun NetworkOptionsCard(selectedNetwork: MutableState) { - val colorScheme = MaterialTheme.colorScheme - Column( - Modifier - .fillMaxWidth() - .background( - color = colorScheme.surfaceVariant, - shape = RoundedCornerShape(16.dp), - ), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.Start, - ) { - Text( - text = "Network", - fontFamily = inter, - fontSize = 14.sp, - color = colorScheme.onSurface, - modifier = - Modifier - .align(Alignment.CenterHorizontally) - .padding(top = 8.dp, bottom = 8.dp), - ) - - HorizontalDivider( - color = colorScheme.outline.copy(alpha = 0.15f), - thickness = 1.dp, - modifier = Modifier.padding(bottom = 8.dp), - ) - - supportedNetworks.forEachIndexed { index, it -> - RadioButtonWithLabel( - label = it.displayString(), - isSelected = selectedNetwork.value == it, - onSelect = { selectedNetwork.value = it }, - ) - if (index == 2) Spacer(modifier = Modifier.padding(bottom = 8.dp)) - } - } -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/ActiveWalletsScreen.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/ActiveWalletsScreen.kt deleted file mode 100644 index ff638d3..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/ActiveWalletsScreen.kt +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.ui.screens.intro - -import androidx.compose.foundation.BorderStroke -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.CardDefaults -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedCard -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.navigation.NavController -import com.composables.icons.lucide.ChevronRight -import com.composables.icons.lucide.Lucide -import org.bitcoindevkit.devkitwallet.data.datastore.StoredWallet -import org.bitcoindevkit.devkitwallet.domain.DwLogger -import org.bitcoindevkit.devkitwallet.domain.DwLogger.LogLevel.INFO -import org.bitcoindevkit.devkitwallet.presentation.WalletCreateType -import org.bitcoindevkit.devkitwallet.presentation.theme.NightGlowSubtle -import org.bitcoindevkit.devkitwallet.presentation.theme.inter -import org.bitcoindevkit.devkitwallet.presentation.ui.components.SecondaryScreensAppBar - -private const val TAG = "ActiveWalletsScreen" - -@Composable -internal fun ActiveWalletsScreen( - activeWallets: List, - navController: NavController, - onBuildWalletButtonClicked: (WalletCreateType) -> Unit, -) { - val colorScheme = MaterialTheme.colorScheme - - Scaffold( - topBar = { - SecondaryScreensAppBar(title = "Choose a Wallet", navigation = { navController.navigateUp() }) - }, - ) { paddingValues -> - Column( - modifier = Modifier - .fillMaxSize() - .padding(paddingValues) - .padding(horizontal = 24.dp, vertical = 16.dp), - verticalArrangement = Arrangement.spacedBy(10.dp), - ) { - if (activeWallets.isEmpty()) { - Text( - text = "No active wallets.", - fontFamily = inter, - fontSize = 14.sp, - color = NightGlowSubtle, - ) - } else { - activeWallets.forEach { wallet -> - OutlinedCard( - onClick = { - DwLogger.log(INFO, "Activating existing wallet: ${wallet.name}") - onBuildWalletButtonClicked(WalletCreateType.LOADEXISTING(wallet)) - }, - shape = RoundedCornerShape(20.dp), - border = BorderStroke(1.5.dp, colorScheme.outline.copy(alpha = 0.12f)), - colors = CardDefaults.outlinedCardColors(containerColor = Color.Transparent), - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(20.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - Column(modifier = Modifier.weight(1f)) { - Text( - text = wallet.name, - fontFamily = inter, - fontSize = 15.sp, - fontWeight = FontWeight.Medium, - color = colorScheme.onSurface, - ) - Row( - horizontalArrangement = Arrangement.spacedBy(8.dp), - modifier = Modifier.padding(top = 4.dp), - ) { - WalletChip(text = wallet.network.name) - WalletChip(text = wallet.scriptType.name) - } - } - Icon( - imageVector = Lucide.ChevronRight, - contentDescription = "Open", - tint = colorScheme.outlineVariant, - modifier = Modifier.size(18.dp), - ) - } - } - } - } - } - } -} - -@Composable -private fun WalletChip(text: String) { - val colorScheme = MaterialTheme.colorScheme - Text( - text = text, - fontFamily = inter, - fontSize = 11.sp, - fontWeight = FontWeight.Medium, - color = colorScheme.onSurfaceVariant, - modifier = Modifier - .padding(0.dp), - ) -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/CreateNewWallet.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/CreateNewWallet.kt deleted file mode 100644 index 3da5792..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/CreateNewWallet.kt +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.ui.screens.intro - -import androidx.compose.foundation.background -import androidx.compose.foundation.border -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.selection.selectable -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.OutlinedTextFieldDefaults -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.navigation.NavController -import org.bitcoindevkit.Network -import org.bitcoindevkit.devkitwallet.data.NewWalletConfig -import org.bitcoindevkit.devkitwallet.data.datastore.ActiveWalletScriptType -import org.bitcoindevkit.devkitwallet.domain.DwLogger -import org.bitcoindevkit.devkitwallet.domain.DwLogger.LogLevel.INFO -import org.bitcoindevkit.devkitwallet.domain.supportedNetworks -import org.bitcoindevkit.devkitwallet.presentation.WalletCreateType -import org.bitcoindevkit.devkitwallet.presentation.theme.NightGlowSubtle -import org.bitcoindevkit.devkitwallet.presentation.theme.inter -import org.bitcoindevkit.devkitwallet.presentation.ui.components.SecondaryScreensAppBar - -@Composable -internal fun CreateNewWalletScreen( - navController: NavController, - onBuildWalletButtonClicked: (WalletCreateType) -> Unit, -) { - val colorScheme = MaterialTheme.colorScheme - - val walletName = remember { mutableStateOf("") } - val selectedNetwork: MutableState = remember { mutableStateOf(Network.SIGNET) } - val selectedScriptType: MutableState = - remember { mutableStateOf(ActiveWalletScriptType.P2TR) } - val scriptTypes = listOf(ActiveWalletScriptType.P2TR, ActiveWalletScriptType.P2WPKH) - - Scaffold( - topBar = { - SecondaryScreensAppBar(title = "Create a New Wallet", navigation = { navController.navigateUp() }) - }, - ) { paddingValues -> - Column( - modifier = Modifier - .fillMaxSize() - .padding(paddingValues) - .padding(horizontal = 24.dp), - ) { - Spacer(Modifier.height(20.dp)) - - // Wallet name - FormLabel("Wallet Name") - OutlinedTextField( - modifier = Modifier.fillMaxWidth(), - value = walletName.value, - onValueChange = { walletName.value = it }, - placeholder = { - Text( - text = "Give your wallet a name", - color = colorScheme.outlineVariant, - fontFamily = inter, - fontSize = 15.sp, - ) - }, - singleLine = true, - textStyle = TextStyle(fontFamily = inter, color = colorScheme.onSurface, fontSize = 15.sp), - colors = OutlinedTextFieldDefaults.colors( - cursorColor = colorScheme.primary, - focusedBorderColor = colorScheme.primary.copy(alpha = 0.40f), - unfocusedBorderColor = colorScheme.outline.copy(alpha = 0.15f), - ), - shape = RoundedCornerShape(16.dp), - ) - - Spacer(Modifier.height(24.dp)) - - // Network - FormLabel("Network") - OptionGroup { - supportedNetworks.forEach { network -> - ThemedRadioOption( - label = network.displayString(), - isSelected = selectedNetwork.value == network, - onSelect = { selectedNetwork.value = network }, - ) - } - } - - Spacer(Modifier.height(24.dp)) - - // Script Type - FormLabel("Script Type") - OptionGroup { - scriptTypes.forEach { scriptType -> - ThemedRadioOption( - label = scriptType.displayString(), - isSelected = selectedScriptType.value == scriptType, - onSelect = { selectedScriptType.value = scriptType }, - ) - } - } - - Spacer(Modifier.weight(1f)) - - // Create button - Button( - onClick = { - val newWalletConfig = NewWalletConfig( - name = walletName.value, - network = selectedNetwork.value, - scriptType = selectedScriptType.value, - ) - DwLogger.log(INFO, "Creating new wallet named ${newWalletConfig.name}") - onBuildWalletButtonClicked(WalletCreateType.FROMSCRATCH(newWalletConfig)) - }, - modifier = Modifier - .fillMaxWidth() - .height(56.dp), - shape = RoundedCornerShape(20.dp), - colors = ButtonDefaults.buttonColors( - containerColor = colorScheme.tertiary, - contentColor = colorScheme.onTertiary, - ), - ) { - Text( - text = "Create Wallet", - fontFamily = inter, - fontSize = 15.sp, - fontWeight = FontWeight.SemiBold, - ) - } - Spacer(Modifier.height(40.dp)) - } - } -} - -@Composable -internal fun FormLabel(text: String) { - Text( - text = text.uppercase(), - fontFamily = inter, - fontSize = 12.sp, - fontWeight = FontWeight.Medium, - color = NightGlowSubtle, - letterSpacing = 1.5.sp, - modifier = Modifier.padding(bottom = 10.dp), - ) -} - -@Composable -internal fun OptionGroup(content: @Composable () -> Unit) { - val colorScheme = MaterialTheme.colorScheme - Column( - modifier = Modifier - .fillMaxWidth() - .border( - width = 1.5.dp, - color = colorScheme.outline.copy(alpha = 0.10f), - shape = RoundedCornerShape(20.dp), - ).padding(8.dp), - ) { - content() - } -} - -@Composable -internal fun ThemedRadioOption(label: String, isSelected: Boolean, onSelect: () -> Unit) { - val colorScheme = MaterialTheme.colorScheme - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(10.dp), - modifier = Modifier - .fillMaxWidth() - .selectable(selected = isSelected, onClick = onSelect) - .padding(horizontal = 16.dp, vertical = 12.dp), - ) { - Box( - modifier = Modifier - .size(22.dp) - .border( - width = 2.dp, - color = if (isSelected) colorScheme.tertiary else colorScheme.outlineVariant, - shape = CircleShape, - ), - contentAlignment = Alignment.Center, - ) { - if (isSelected) { - Box( - modifier = Modifier - .size(10.dp) - .background(colorScheme.tertiary, CircleShape), - ) - } - } - Text( - text = label, - fontFamily = inter, - fontSize = 14.sp, - color = colorScheme.onSurface, - ) - } -} - -fun ActiveWalletScriptType.displayString(): String { - return when (this) { - ActiveWalletScriptType.P2TR -> "P2TR (Taproot, BIP-86)" - ActiveWalletScriptType.P2WPKH -> "P2WPKH (Native Segwit, BIP-84)" - ActiveWalletScriptType.UNKNOWN -> TODO() - } -} - -fun Network.displayString(): String { - return when (this) { - Network.TESTNET -> "Testnet 3" - Network.TESTNET4 -> "Testnet 4" - Network.REGTEST -> "Regtest" - Network.SIGNET -> "Signet" - Network.BITCOIN -> TODO() - } -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/OnboardingScreen.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/OnboardingScreen.kt deleted file mode 100644 index e960236..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/OnboardingScreen.kt +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.ui.screens.intro - -import androidx.compose.foundation.Image -import androidx.compose.foundation.background -import androidx.compose.foundation.border -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.pager.HorizontalPager -import androidx.compose.foundation.pager.rememberPagerState -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import kotlinx.coroutines.launch -import org.bitcoindevkit.devkitwallet.R -import org.bitcoindevkit.devkitwallet.presentation.theme.inter - -private val surface = Color(0xFF1C1B1F) -private val onSurface = Color(0xFFE6E1E5) -private val subtle = Color(0xFF79747E) -private val accent = Color(0xFFF2D2B6) - -@Composable -fun OnboardingScreen(onFinishOnboarding: () -> Unit) { - val pagerState = rememberPagerState(initialPage = 1, pageCount = { 4 }) - val coroutineScope = rememberCoroutineScope() - - @Suppress("ktlint:standard:max-line-length") - val messages = listOf( - "Easter egg #1: \uD83E\uDD5A", - "Welcome to the Devkit Wallet! This app is a playground for developers and bitcoin enthusiasts to experiment with bitcoin's test networks.", - "It is developed with the Bitcoin Dev Kit, a powerful set of libraries produced and maintained by the Bitcoin Dev Kit Foundation.\n\nThis version of the app is using Compact Block Filters to sync its wallets.", - "The Foundation maintains this app as a way to showcase the capabilities of the Bitcoin Dev Kit and to provide a starting point for developers to build their own apps.\n\nIt is not a production application, and only works for testnet3, testnet4, signet, and regtest. Have fun!" - ) - - Column( - modifier = Modifier - .fillMaxSize() - .background(surface) - .padding(horizontal = 32.dp), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Spacer(Modifier.height(120.dp)) - - // Logo - Box( - modifier = Modifier - .size(100.dp) - .border( - width = 2.dp, - color = accent.copy(alpha = 0.20f), - shape = CircleShape, - ), - contentAlignment = Alignment.Center, - ) { - Image( - painter = painterResource(id = R.drawable.bdk_logo), - contentDescription = "Bitcoin Dev Kit logo", - modifier = Modifier.size(56.dp), - ) - } - - Spacer(Modifier.height(16.dp)) - - Text( - text = "Devkit Wallet", - fontFamily = inter, - fontSize = 24.sp, - fontWeight = FontWeight.Light, - color = onSurface, - ) - Text( - text = "BITCOIN DEVELOPMENT KIT", - fontFamily = inter, - fontSize = 11.sp, - color = subtle, - letterSpacing = 1.5.sp, - ) - - Spacer(Modifier.height(48.dp)) - - // Pager - HorizontalPager( - state = pagerState, - modifier = Modifier - .fillMaxWidth() - .weight(1f), - ) { page -> - Text( - text = messages[page], - fontFamily = inter, - fontSize = 15.sp, - lineHeight = 24.sp, - color = onSurface.copy(alpha = 0.85f), - textAlign = TextAlign.Center, - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 8.dp), - ) - } - - // Page indicators - Row( - horizontalArrangement = Arrangement.Center, - modifier = Modifier.padding(bottom = 32.dp), - ) { - repeat(3) { index -> - val isSelected = pagerState.currentPage == index + 1 - Box( - modifier = Modifier - .padding(horizontal = 6.dp) - .size(if (isSelected) 10.dp else 8.dp) - .clip(CircleShape) - .background( - if (isSelected) accent else accent.copy(alpha = 0.25f) - ), - ) - } - } - - // Navigation buttons - Row( - modifier = Modifier - .fillMaxWidth() - .padding(bottom = 40.dp), - horizontalArrangement = Arrangement.SpaceBetween, - ) { - Text( - text = "Previous", - fontFamily = inter, - fontSize = 14.sp, - fontWeight = FontWeight.Medium, - color = subtle, - modifier = Modifier - .clickable( - indication = null, - interactionSource = remember { MutableInteractionSource() }, - ) { - coroutineScope.launch { - pagerState.animateScrollToPage((pagerState.currentPage - 1).coerceIn(0, 3)) - } - }.border( - width = 1.5.dp, - color = subtle.copy(alpha = 0.20f), - shape = RoundedCornerShape(12.dp), - ).padding(horizontal = 20.dp, vertical = 10.dp), - ) - Text( - text = if (pagerState.currentPage < 3) "Next" else "Get Started", - fontFamily = inter, - fontSize = 14.sp, - fontWeight = FontWeight.Medium, - color = if (pagerState.currentPage < 3) onSurface else surface, - modifier = Modifier - .clickable( - indication = null, - interactionSource = remember { MutableInteractionSource() }, - ) { - if (pagerState.currentPage < 3) { - coroutineScope.launch { - pagerState.animateScrollToPage((pagerState.currentPage + 1).coerceIn(0, 3)) - } - } else { - onFinishOnboarding() - } - }.then( - if (pagerState.currentPage < 3) { - Modifier.border( - width = 1.5.dp, - color = accent.copy(alpha = 0.30f), - shape = RoundedCornerShape(12.dp), - ) - } else { - Modifier - .background(accent, RoundedCornerShape(12.dp)) - } - ).padding(horizontal = 20.dp, vertical = 10.dp), - ) - } - } -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/RecoverWalletScreen.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/RecoverWalletScreen.kt deleted file mode 100644 index 14e20ff..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/RecoverWalletScreen.kt +++ /dev/null @@ -1,404 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.ui.screens.intro - -import android.util.Log -import androidx.compose.foundation.border -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.selection.selectable -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.OutlinedTextFieldDefaults -import androidx.compose.material3.Scaffold -import androidx.compose.material3.SnackbarHost -import androidx.compose.material3.SnackbarHostState -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.navigation.NavController -import kotlinx.coroutines.launch -import org.bitcoindevkit.Descriptor -import org.bitcoindevkit.DescriptorSecretKey -import org.bitcoindevkit.KeychainKind -import org.bitcoindevkit.Mnemonic -import org.bitcoindevkit.Network -import org.bitcoindevkit.NetworkKind -import org.bitcoindevkit.devkitwallet.data.RecoverWalletConfig -import org.bitcoindevkit.devkitwallet.data.datastore.ActiveWalletScriptType -import org.bitcoindevkit.devkitwallet.domain.DwLogger -import org.bitcoindevkit.devkitwallet.domain.DwLogger.LogLevel.INFO -import org.bitcoindevkit.devkitwallet.domain.bip39WordList -import org.bitcoindevkit.devkitwallet.domain.createScriptAppropriateDescriptor -import org.bitcoindevkit.devkitwallet.domain.supportedNetworks -import org.bitcoindevkit.devkitwallet.presentation.WalletCreateType -import org.bitcoindevkit.devkitwallet.presentation.theme.inter -import org.bitcoindevkit.devkitwallet.presentation.ui.components.SecondaryScreensAppBar - -@Composable -internal fun RecoverWalletScreen(onAction: (WalletCreateType) -> Unit, navController: NavController) { - val colorScheme = MaterialTheme.colorScheme - val scope = rememberCoroutineScope() - val snackbarHostState = remember { SnackbarHostState() } - - var selectedTab by remember { mutableStateOf(0) } - val tabs = listOf("Recovery Phrase", "Descriptor") - - var walletName by remember { mutableStateOf("") } - val selectedNetwork: MutableState = remember { mutableStateOf(Network.SIGNET) } - val selectedScriptType: MutableState = - remember { mutableStateOf(ActiveWalletScriptType.P2TR) } - val scriptTypes = listOf(ActiveWalletScriptType.P2TR, ActiveWalletScriptType.P2WPKH) - - var recoveryPhrase by remember { mutableStateOf("") } - var descriptorString by remember { mutableStateOf("") } - var changeDescriptorString by remember { mutableStateOf("") } - - Scaffold( - topBar = { - SecondaryScreensAppBar(title = "Recover a Wallet", navigation = { navController.navigateUp() }) - }, - snackbarHost = { - SnackbarHost(hostState = snackbarHostState) - }, - ) { paddingValues -> - Column( - modifier = Modifier - .fillMaxSize() - .padding(paddingValues) - .padding(horizontal = 24.dp) - .verticalScroll(rememberScrollState()), - ) { - Spacer(Modifier.height(20.dp)) - - // Tab selector - FormLabel("Recovery Method") - Row( - modifier = Modifier - .fillMaxWidth() - .border( - width = 1.5.dp, - color = colorScheme.outline.copy(alpha = 0.10f), - shape = RoundedCornerShape(20.dp), - ).padding(4.dp), - horizontalArrangement = Arrangement.spacedBy(0.dp), - ) { - tabs.forEachIndexed { index, label -> - val isSelected = selectedTab == index - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.Center, - modifier = Modifier - .weight(1f) - .selectable(selected = isSelected, onClick = { selectedTab = index }) - .then( - if (isSelected) { - Modifier.border( - width = 1.5.dp, - color = colorScheme.primary.copy(alpha = 0.30f), - shape = RoundedCornerShape(16.dp), - ) - } else { - Modifier - } - ).padding(horizontal = 16.dp, vertical = 12.dp), - ) { - Text( - text = label, - fontFamily = inter, - fontSize = 13.sp, - fontWeight = if (isSelected) FontWeight.Medium else FontWeight.Normal, - color = if (isSelected) colorScheme.primary else colorScheme.onSurfaceVariant, - ) - } - } - } - - Spacer(Modifier.height(24.dp)) - - // Wallet name (always shown) - FormLabel("Wallet Name") - OutlinedTextField( - modifier = Modifier.fillMaxWidth(), - value = walletName, - onValueChange = { walletName = it }, - placeholder = { - Text( - text = "Give your wallet a name", - color = colorScheme.outlineVariant, - fontFamily = inter, - fontSize = 15.sp, - ) - }, - singleLine = true, - textStyle = TextStyle(fontFamily = inter, color = colorScheme.onSurface, fontSize = 15.sp), - colors = OutlinedTextFieldDefaults.colors( - cursorColor = colorScheme.primary, - focusedBorderColor = colorScheme.primary.copy(alpha = 0.40f), - unfocusedBorderColor = colorScheme.outline.copy(alpha = 0.15f), - ), - shape = RoundedCornerShape(16.dp), - ) - - Spacer(Modifier.height(24.dp)) - - if (selectedTab == 0) { - // Recovery Phrase tab - // Network - FormLabel("Network") - OptionGroup { - supportedNetworks.forEach { network -> - ThemedRadioOption( - label = network.displayString(), - isSelected = selectedNetwork.value == network, - onSelect = { selectedNetwork.value = network }, - ) - } - } - - Spacer(Modifier.height(24.dp)) - - // Script Type - FormLabel("Script Type") - OptionGroup { - scriptTypes.forEach { scriptType -> - ThemedRadioOption( - label = scriptType.displayString(), - isSelected = selectedScriptType.value == scriptType, - onSelect = { selectedScriptType.value = scriptType }, - ) - } - } - - Spacer(Modifier.height(24.dp)) - - // Recovery phrase input - FormLabel("Recovery Phrase") - OutlinedTextField( - modifier = Modifier.fillMaxWidth(), - value = recoveryPhrase, - onValueChange = { recoveryPhrase = it }, - placeholder = { - Text( - text = "Enter your 12-word recovery phrase", - color = colorScheme.outlineVariant, - fontFamily = inter, - fontSize = 15.sp, - ) - }, - singleLine = false, - minLines = 3, - textStyle = TextStyle(fontFamily = inter, color = colorScheme.onSurface, fontSize = 14.sp), - colors = OutlinedTextFieldDefaults.colors( - cursorColor = colorScheme.primary, - focusedBorderColor = colorScheme.primary.copy(alpha = 0.40f), - unfocusedBorderColor = colorScheme.outline.copy(alpha = 0.15f), - ), - shape = RoundedCornerShape(16.dp), - ) - } else { - // Descriptor tab - // Network - FormLabel("Network") - OptionGroup { - supportedNetworks.forEach { network -> - ThemedRadioOption( - label = network.displayString(), - isSelected = selectedNetwork.value == network, - onSelect = { selectedNetwork.value = network }, - ) - } - } - - Spacer(Modifier.height(24.dp)) - - // Descriptor input - FormLabel("Descriptor") - OutlinedTextField( - modifier = Modifier.fillMaxWidth(), - value = descriptorString, - onValueChange = { descriptorString = it }, - placeholder = { - Text( - text = "Input your descriptor here", - color = colorScheme.outlineVariant, - fontFamily = inter, - fontSize = 15.sp, - ) - }, - singleLine = false, - minLines = 4, - textStyle = TextStyle(fontFamily = inter, color = colorScheme.onSurface, fontSize = 13.sp), - colors = OutlinedTextFieldDefaults.colors( - cursorColor = colorScheme.primary, - focusedBorderColor = colorScheme.primary.copy(alpha = 0.40f), - unfocusedBorderColor = colorScheme.outline.copy(alpha = 0.15f), - ), - shape = RoundedCornerShape(16.dp), - ) - - Spacer(Modifier.height(16.dp)) - - // Change descriptor input - FormLabel("Change Descriptor") - OutlinedTextField( - modifier = Modifier.fillMaxWidth(), - value = changeDescriptorString, - onValueChange = { changeDescriptorString = it }, - placeholder = { - Text( - text = "Input your change descriptor here", - color = colorScheme.outlineVariant, - fontFamily = inter, - fontSize = 15.sp, - ) - }, - singleLine = false, - minLines = 4, - textStyle = TextStyle(fontFamily = inter, color = colorScheme.onSurface, fontSize = 13.sp), - colors = OutlinedTextFieldDefaults.colors( - cursorColor = colorScheme.primary, - focusedBorderColor = colorScheme.primary.copy(alpha = 0.40f), - unfocusedBorderColor = colorScheme.outline.copy(alpha = 0.15f), - ), - shape = RoundedCornerShape(16.dp), - ) - } - - Spacer(Modifier.weight(1f)) - - // Recover button - Button( - onClick = { - if (selectedTab == 0) { - // Recovery phrase flow - if (recoveryPhrase.isEmpty()) { - scope.launch { - snackbarHostState.showSnackbar( - "You must provide a recovery phrase to recover a wallet.", - ) - } - return@Button - } - Log.i("RecoverWalletScreen", "Recovering wallet with recovery phrase") - val parsingResult = parseRecoveryPhrase(recoveryPhrase) - - if (parsingResult is RecoveryPhraseValidationResult.Invalid) { - scope.launch { - snackbarHostState.showSnackbar(parsingResult.reason) - } - } else if (parsingResult is RecoveryPhraseValidationResult.ProbablyValid) { - val mnemonic = Mnemonic.fromString(parsingResult.recoveryPhrase) - val bip32ExtendedRootKey = DescriptorSecretKey(NetworkKind.TEST, mnemonic, null) - val descriptor = - createScriptAppropriateDescriptor( - scriptType = selectedScriptType.value, - bip32ExtendedRootKey = bip32ExtendedRootKey, - keychain = KeychainKind.EXTERNAL, - ) - val changeDescriptor = - createScriptAppropriateDescriptor( - scriptType = selectedScriptType.value, - bip32ExtendedRootKey = bip32ExtendedRootKey, - keychain = KeychainKind.INTERNAL, - ) - val recoverWalletConfig = - RecoverWalletConfig( - name = walletName, - network = selectedNetwork.value, - scriptType = selectedScriptType.value, - descriptor = descriptor, - changeDescriptor = changeDescriptor, - recoveryPhrase = parsingResult.recoveryPhrase, - ) - DwLogger.log(INFO, "Recovering wallet with recovery phrase (name: $walletName)") - onAction(WalletCreateType.RECOVER(recoverWalletConfig)) - } - } else { - // Descriptor flow - if (descriptorString.isEmpty() || changeDescriptorString.isEmpty()) { - scope.launch { - snackbarHostState.showSnackbar( - "You must provide both a descriptor and a change descriptor.", - ) - } - return@Button - } - Log.i("RecoverWalletScreen", "Recovering wallet with descriptors") - val descriptor = Descriptor(descriptorString, NetworkKind.TEST) - val changeDescriptor = Descriptor(changeDescriptorString, NetworkKind.TEST) - val recoverWalletConfig = - RecoverWalletConfig( - name = walletName, - network = selectedNetwork.value, - scriptType = null, - descriptor = descriptor, - changeDescriptor = changeDescriptor, - recoveryPhrase = null, - ) - DwLogger.log(INFO, "Recovering wallet with descriptors (name: $walletName)") - onAction(WalletCreateType.RECOVER(recoverWalletConfig)) - } - }, - modifier = Modifier - .fillMaxWidth() - .height(56.dp), - shape = RoundedCornerShape(20.dp), - colors = ButtonDefaults.buttonColors( - containerColor = colorScheme.primary, - contentColor = colorScheme.onPrimary, - ), - ) { - Text( - text = "Recover Wallet", - fontFamily = inter, - fontSize = 15.sp, - fontWeight = FontWeight.SemiBold, - ) - } - Spacer(Modifier.height(40.dp)) - } - } -} - -private fun parseRecoveryPhrase(recoveryPhrase: String): RecoveryPhraseValidationResult { - val words = recoveryPhrase.trim().split(" ") - if (words.size != 12) { - return RecoveryPhraseValidationResult.Invalid("Recovery phrase must have 12 words") - } - if (words.any { it !in bip39WordList }) { - return RecoveryPhraseValidationResult.Invalid("Invalid word in recovery phrase") - } - return RecoveryPhraseValidationResult.ProbablyValid(recoveryPhrase) -} - -sealed class RecoveryPhraseValidationResult { - data class ProbablyValid(val recoveryPhrase: String) : RecoveryPhraseValidationResult() - - data class Invalid(val reason: String) : RecoveryPhraseValidationResult() -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/WalletChoiceScreen.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/WalletChoiceScreen.kt deleted file mode 100644 index 84749ce..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/WalletChoiceScreen.kt +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.ui.screens.intro - -import androidx.compose.foundation.BorderStroke -import androidx.compose.foundation.border -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.CardDefaults -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedCard -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.navigation.NavController -import com.composables.icons.lucide.List -import com.composables.icons.lucide.Lucide -import com.composables.icons.lucide.Plus -import com.composables.icons.lucide.RotateCcw -import org.bitcoindevkit.devkitwallet.presentation.navigation.ActiveWalletsScreen -import org.bitcoindevkit.devkitwallet.presentation.navigation.CreateNewWalletScreen -import org.bitcoindevkit.devkitwallet.presentation.navigation.WalletRecoveryScreen -import org.bitcoindevkit.devkitwallet.presentation.theme.NightGlowSubtle -import org.bitcoindevkit.devkitwallet.presentation.theme.inter - -@Composable -internal fun WalletChoiceScreen(navController: NavController) { - val colorScheme = MaterialTheme.colorScheme - - Scaffold { paddingValues -> - Column( - modifier = Modifier - .fillMaxSize() - .padding(paddingValues), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center, - ) { - // Logo area - Box( - modifier = Modifier - .size(72.dp) - .border( - width = 2.dp, - color = colorScheme.primary.copy(alpha = 0.20f), - shape = CircleShape, - ), - contentAlignment = Alignment.Center, - ) { - Text( - text = "\u20BF", - color = colorScheme.primary, - fontSize = 32.sp, - fontWeight = FontWeight.Bold, - ) - } - - Spacer(Modifier.height(20.dp)) - - Text( - text = "Devkit Wallet", - fontFamily = inter, - fontSize = 28.sp, - fontWeight = FontWeight.Light, - color = colorScheme.onSurface, - ) - Text( - text = "BITCOIN DEVELOPMENT KIT", - fontSize = 13.sp, - color = NightGlowSubtle, - letterSpacing = 1.sp, - ) - - Spacer(Modifier.height(64.dp)) - - // Buttons - Column( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 48.dp), - verticalArrangement = Arrangement.spacedBy(12.dp), - ) { - WelcomeButton( - icon = Lucide.List, - iconTint = colorScheme.primary, - title = "Use an Active Wallet", - description = "Open an existing wallet on this device", - borderColor = colorScheme.outline.copy(alpha = 0.15f), - onClick = { navController.navigate(ActiveWalletsScreen) }, - ) - WelcomeButton( - icon = Lucide.Plus, - iconTint = colorScheme.tertiary, - title = "Create a New Wallet", - description = "Generate fresh keys and start from scratch", - borderColor = colorScheme.outline.copy(alpha = 0.15f), - onClick = { navController.navigate(CreateNewWalletScreen) }, - ) - WelcomeButton( - icon = Lucide.RotateCcw, - iconTint = colorScheme.secondary, - title = "Recover an Existing Wallet", - description = "Import from descriptor or recovery phrase", - borderColor = colorScheme.outline.copy(alpha = 0.15f), - onClick = { navController.navigate(WalletRecoveryScreen) }, - ) - } - } - } -} - -@Composable -private fun WelcomeButton( - icon: androidx.compose.ui.graphics.vector.ImageVector, - iconTint: Color, - title: String, - description: String, - borderColor: Color, - onClick: () -> Unit, -) { - OutlinedCard( - onClick = onClick, - shape = RoundedCornerShape(20.dp), - border = BorderStroke(1.5.dp, borderColor), - colors = CardDefaults.outlinedCardColors(containerColor = Color.Transparent), - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(20.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(16.dp), - ) { - Box( - modifier = Modifier - .size(44.dp) - .border( - width = 1.dp, - color = iconTint.copy(alpha = 0.15f), - shape = RoundedCornerShape(14.dp), - ), - contentAlignment = Alignment.Center, - ) { - Icon( - imageVector = icon, - contentDescription = null, - tint = iconTint, - modifier = Modifier.size(22.dp), - ) - } - Column { - Text( - text = title, - fontFamily = inter, - fontSize = 15.sp, - fontWeight = FontWeight.Medium, - color = MaterialTheme.colorScheme.onSurface, - ) - Text( - text = description, - fontFamily = inter, - fontSize = 12.sp, - color = NightGlowSubtle, - ) - } - } - } -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/AboutScreen.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/AboutScreen.kt deleted file mode 100644 index e14c22f..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/AboutScreen.kt +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.ui.screens.settings - -import androidx.compose.foundation.Image -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalUriHandler -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.style.TextDecoration -import androidx.compose.ui.tooling.preview.Devices -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.navigation.NavController -import androidx.navigation.compose.rememberNavController -import org.bitcoindevkit.devkitwallet.R -import org.bitcoindevkit.devkitwallet.presentation.theme.inter -import org.bitcoindevkit.devkitwallet.presentation.ui.components.SecondaryScreensAppBar - -private val message: String = - """ - This wallet is build for: - - 1. Developers interested in learning how to leverage the Bitcoin Development Kit on Android. - - 2. Any bitcoiner looking for a Signet/Testnet/Regtest wallet! - """.trimIndent() - -@Composable -internal fun AboutScreen(navController: NavController) { - val colorScheme = MaterialTheme.colorScheme - val mUriHandler = LocalUriHandler.current - val openSourceRepository = - remember { { mUriHandler.openUri("https://github.com/bitcoindevkit/bdk-kotlin-example-wallet") } } - - Scaffold( - topBar = { - SecondaryScreensAppBar( - title = "About", - navigation = { navController.popBackStack() }, - ) - }, - containerColor = colorScheme.surface, - ) { paddingValues -> - Column( - modifier = - Modifier - .fillMaxSize() - .padding(paddingValues) - .padding(start = 16.dp, end = 16.dp, top = 16.dp, bottom = 100.dp), - verticalArrangement = Arrangement.Top, - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Spacer(modifier = Modifier.padding(24.dp)) - Image( - painter = painterResource(id = R.drawable.bdk_logo), - contentDescription = "Old School BDK Logo", - Modifier.size(180.dp), - ) - Spacer(modifier = Modifier.padding(24.dp)) - Text( - text = message, - color = colorScheme.onSurface, - fontFamily = inter, - fontSize = 16.sp, - lineHeight = 26.sp, - modifier = Modifier.padding(all = 8.dp), - ) - Spacer(modifier = Modifier.padding(8.dp)) - Text( - text = "You are using the Compact Block Filters (CBF) version of the wallet.", - color = colorScheme.onSurface, - fontFamily = inter, - fontSize = 16.sp, - lineHeight = 26.sp, - modifier = Modifier.padding(all = 8.dp), - ) - Spacer(modifier = Modifier.padding(8.dp)) - Text( - text = "Check out the source code for the wallet on GitHub.", - color = colorScheme.primary, - fontFamily = inter, - fontSize = 16.sp, - textDecoration = TextDecoration.Underline, - lineHeight = 26.sp, - modifier = - Modifier - .padding(all = 8.dp) - .clickable(onClick = openSourceRepository), - ) - } - } -} - -@Preview(device = Devices.PIXEL_4, showBackground = true) -@Composable -internal fun PreviewAboutScreen() { - AboutScreen(rememberNavController()) -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/BlockchainClientScreen.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/BlockchainClientScreen.kt deleted file mode 100644 index 7b4e1e6..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/BlockchainClientScreen.kt +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.ui.screens.settings - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.navigation.NavController -import org.bitcoindevkit.devkitwallet.presentation.theme.inter -import org.bitcoindevkit.devkitwallet.presentation.ui.components.NeutralButton -import org.bitcoindevkit.devkitwallet.presentation.ui.components.SecondaryScreensAppBar -import org.bitcoindevkit.devkitwallet.presentation.viewmodels.mvi.CbfNodeStatus -import org.bitcoindevkit.devkitwallet.presentation.viewmodels.mvi.WalletScreenAction -import org.bitcoindevkit.devkitwallet.presentation.viewmodels.mvi.WalletScreenState - -@Composable -internal fun BlockchainClientScreen( - state: WalletScreenState, - onAction: (WalletScreenAction) -> Unit, - navController: NavController, -) { - val colorScheme = MaterialTheme.colorScheme - - Scaffold( - topBar = { - SecondaryScreensAppBar( - title = "Compact Block Filters Node", - navigation = { navController.popBackStack() }, - ) - }, - containerColor = colorScheme.surface, - ) { paddingValues -> - Column( - verticalArrangement = Arrangement.Top, - horizontalAlignment = Alignment.CenterHorizontally, - modifier = - Modifier - .fillMaxSize() - .padding(paddingValues) - .padding(vertical = 32.dp, horizontal = 16.dp), - ) { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween, - modifier = Modifier.fillMaxWidth(), - ) { - val status = if (state.kyotoNodeStatus == CbfNodeStatus.Running) "Online" else "Offline" - Text( - text = "CBF Node Status: $status", - color = colorScheme.onSurface, - fontSize = 14.sp, - fontFamily = inter, - textAlign = TextAlign.Start, - ) - Box( - modifier = - Modifier - .padding(horizontal = 8.dp) - .size(size = 21.dp) - .clip(shape = CircleShape) - .background( - if (state.kyotoNodeStatus == CbfNodeStatus.Running) { - Color(0xFF8FD998) - } else { - Color(0xFFE76F51) - } - ), - ) - } - - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween, - modifier = Modifier.fillMaxWidth().padding(top = 16.dp), - ) { - Text( - text = "Latest known block:", - color = colorScheme.onSurface, - fontSize = 14.sp, - fontFamily = inter, - textAlign = TextAlign.Start, - ) - Text( - text = "${state.bestBlockHeight}", - color = colorScheme.onSurface, - fontSize = 14.sp, - fontFamily = inter, - textAlign = TextAlign.Start, - ) - } - - Spacer(modifier = Modifier.padding(16.dp)) - - NeutralButton( - text = "Start Node", - enabled = state.kyotoNodeStatus == CbfNodeStatus.Stopped, - onClick = { onAction(WalletScreenAction.ActivateCbfNode) }, - ) - NeutralButton( - text = "Stop Node", - enabled = state.kyotoNodeStatus == CbfNodeStatus.Running, - onClick = { onAction(WalletScreenAction.StopKyotoNode) }, - ) - } - } -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/CustomBlockchainClient.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/CustomBlockchainClient.kt deleted file mode 100644 index 7cff349..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/CustomBlockchainClient.kt +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.ui.screens.settings - -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Scaffold -import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalFocusManager -import androidx.compose.ui.unit.dp -import androidx.navigation.NavController -import org.bitcoindevkit.devkitwallet.presentation.ui.components.SecondaryScreensAppBar - -@Composable -internal fun CustomBlockchainClient(navController: NavController) { - val focusManager = LocalFocusManager.current - val electrumServer: MutableState = remember { mutableStateOf("") } - val isChecked: MutableState = remember { mutableStateOf(false) } - - Scaffold( - topBar = { - SecondaryScreensAppBar( - title = "Custom Blockchain Client", - navigation = { navController.popBackStack() }, - ) - }, - containerColor = MaterialTheme.colorScheme.surface, - ) { paddingValues -> - Column( - modifier = - Modifier - .fillMaxSize() - .padding(paddingValues) - .padding(all = 16.dp), - ) { - } - } -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/LogsScreen.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/LogsScreen.kt deleted file mode 100644 index b1118af..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/LogsScreen.kt +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.ui.screens.settings - -import androidx.compose.foundation.horizontalScroll -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.rememberScrollState -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.navigation.NavController -import org.bitcoindevkit.devkitwallet.domain.DwLogger -import org.bitcoindevkit.devkitwallet.presentation.theme.inter -import org.bitcoindevkit.devkitwallet.presentation.ui.components.SecondaryScreensAppBar - -@Composable -fun LogsScreen(navController: NavController) { - val logs: List = remember { DwLogger.getLogs() } - val colorScheme = MaterialTheme.colorScheme - - Scaffold( - topBar = { - SecondaryScreensAppBar( - title = "Logs", - navigation = { navController.popBackStack() }, - ) - }, - containerColor = colorScheme.surface, - ) { paddingValues -> - LazyColumn( - modifier = - Modifier - .fillMaxSize() - .padding(paddingValues) - .padding(16.dp), - ) { - items(logs) { logLine -> - Text( - text = logLine, - color = colorScheme.onSurface, - fontFamily = inter, - fontSize = 14.sp, - maxLines = 1, - overflow = TextOverflow.Visible, - modifier = - Modifier - .fillMaxWidth() - .horizontalScroll(rememberScrollState()), - ) - } - } - } -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/RecoveryDataScreen.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/RecoveryDataScreen.kt deleted file mode 100644 index d02b277..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/RecoveryDataScreen.kt +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.ui.screens.settings - -import android.content.ClipData -import android.content.ClipboardManager -import android.content.Context -import androidx.compose.animation.Crossfade -import androidx.compose.animation.core.tween -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.text.selection.SelectionContainer -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.mutableIntStateOf -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.unit.dp -import androidx.navigation.NavController -import com.composables.icons.lucide.ClipboardCopy -import com.composables.icons.lucide.Lucide -import org.bitcoindevkit.devkitwallet.domain.WalletSecrets -import org.bitcoindevkit.devkitwallet.presentation.theme.googleSansCode -import org.bitcoindevkit.devkitwallet.presentation.theme.inter -import org.bitcoindevkit.devkitwallet.presentation.ui.components.NeutralButton -import org.bitcoindevkit.devkitwallet.presentation.ui.components.SecondaryScreensAppBar - -private val MESSAGE: String = - """ - The next screen will show your recovery phrase and descriptors. Make sure no one else is looking at your screen. - """.trimIndent() - -@Composable -internal fun RecoveryDataScreen(walletSecrets: WalletSecrets, navController: NavController) { - val (currentIndex, setCurrentIndex) = remember { mutableIntStateOf(0) } - val colorScheme = MaterialTheme.colorScheme - - Scaffold( - topBar = { - SecondaryScreensAppBar( - title = "Your Wallet Recovery Data", - navigation = { navController.popBackStack() }, - ) - }, - containerColor = colorScheme.surface, - ) { paddingValues -> - Crossfade( - modifier = Modifier.padding(paddingValues), - targetState = currentIndex, - label = "", - animationSpec = - tween( - durationMillis = 1000, - delayMillis = 200, - ), - ) { screen -> - when (screen) { - 0 -> WarningText(setCurrentIndex = setCurrentIndex) - 1 -> RecoveryPhrase(walletSecrets = walletSecrets) - } - } - } -} - -@Composable -fun WarningText(setCurrentIndex: (Int) -> Unit) { - val colorScheme = MaterialTheme.colorScheme - Column( - modifier = - Modifier - .fillMaxSize() - .padding(horizontal = 32.dp, vertical = 16.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center, - ) { - Text( - text = MESSAGE, - color = colorScheme.onSurface, - fontFamily = inter, - ) - Spacer(modifier = Modifier.padding(16.dp)) - NeutralButton( - text = "See my recovery data", - enabled = true, - ) { setCurrentIndex(1) } - } -} - -@Composable -fun RecoveryPhrase(walletSecrets: WalletSecrets) { - val context = LocalContext.current - val colorScheme = MaterialTheme.colorScheme - Column( - modifier = - Modifier - .fillMaxSize() - .padding(all = 32.dp), - ) { - Text( - text = "Write down your recovery phrase and keep it in a safe place.", - color = colorScheme.onSurface, - fontFamily = inter, - ) - Spacer(modifier = Modifier.padding(8.dp)) - Box { - SelectionContainer { - Text( - modifier = - Modifier - .clickable { - simpleCopyClipboard( - walletSecrets.recoveryPhrase, - context, - ) - }.background( - color = colorScheme.surfaceVariant, - shape = RoundedCornerShape(16.dp), - ).padding(12.dp), - text = walletSecrets.recoveryPhrase, - fontFamily = googleSansCode, - color = colorScheme.onSurface, - ) - } - Icon( - Lucide.ClipboardCopy, - tint = colorScheme.onSurface.copy(alpha = 0.5f), - contentDescription = "Copy to clipboard", - modifier = - Modifier - .padding(8.dp) - .size(20.dp) - .align(Alignment.BottomEnd), - ) - } - Spacer(modifier = Modifier.padding(16.dp)) - Text( - text = "These are your descriptors.", - color = colorScheme.onSurface, - fontFamily = inter, - ) - Spacer(modifier = Modifier.padding(8.dp)) - Box { - SelectionContainer { - Text( - modifier = - Modifier - .clickable { - simpleCopyClipboard( - walletSecrets.descriptor.toStringWithSecret(), - context, - ) - }.background( - color = colorScheme.surfaceVariant, - shape = RoundedCornerShape(16.dp), - ).padding(12.dp), - text = walletSecrets.descriptor.toStringWithSecret(), - fontFamily = googleSansCode, - color = colorScheme.onSurface, - ) - } - Icon( - Lucide.ClipboardCopy, - tint = colorScheme.onSurface.copy(alpha = 0.5f), - contentDescription = "Copy to clipboard", - modifier = - Modifier - .padding(8.dp) - .size(20.dp) - .align(Alignment.BottomEnd), - ) - } - Spacer(modifier = Modifier.padding(4.dp)) - Box { - SelectionContainer { - Text( - modifier = - Modifier - .clickable { - simpleCopyClipboard( - walletSecrets.changeDescriptor.toStringWithSecret(), - context, - ) - }.background( - color = colorScheme.surfaceVariant, - shape = RoundedCornerShape(16.dp), - ).padding(12.dp), - text = walletSecrets.changeDescriptor.toStringWithSecret(), - fontFamily = googleSansCode, - color = colorScheme.onSurface, - ) - } - Icon( - Lucide.ClipboardCopy, - tint = colorScheme.onSurface.copy(alpha = 0.5f), - contentDescription = "Copy to clipboard", - modifier = - Modifier - .padding(8.dp) - .size(20.dp) - .align(Alignment.BottomEnd), - ) - } - } -} - -fun simpleCopyClipboard(content: String, context: Context) { - val clipboard: ClipboardManager = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager - val clip: ClipData = ClipData.newPlainText("", content) - clipboard.setPrimaryClip(clip) -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/SettingsScreen.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/SettingsScreen.kt deleted file mode 100644 index df8fcd7..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/SettingsScreen.kt +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.ui.screens.settings - -import androidx.compose.foundation.background -import androidx.compose.foundation.border -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.navigation.NavController -import com.composables.icons.lucide.Info -import com.composables.icons.lucide.Lucide -import com.composables.icons.lucide.Palette -import com.composables.icons.lucide.ScrollText -import org.bitcoindevkit.devkitwallet.presentation.navigation.AboutScreen -import org.bitcoindevkit.devkitwallet.presentation.navigation.LogsScreen -import org.bitcoindevkit.devkitwallet.presentation.navigation.ThemeScreen -import org.bitcoindevkit.devkitwallet.presentation.theme.DayGlowHistoryAccent -import org.bitcoindevkit.devkitwallet.presentation.theme.inter -import org.bitcoindevkit.devkitwallet.presentation.ui.components.SecondaryScreensAppBar - -@Composable -internal fun SettingsScreen(navController: NavController) { - val colorScheme = MaterialTheme.colorScheme - - Scaffold( - topBar = { - SecondaryScreensAppBar( - title = "Settings", - navigation = { navController.popBackStack() }, - ) - }, - containerColor = colorScheme.surface, - ) { paddingValues -> - Column( - modifier = Modifier - .fillMaxSize() - .padding(paddingValues) - .padding(horizontal = 20.dp, vertical = 16.dp), - ) { - Column( - modifier = Modifier - .fillMaxWidth() - .border( - width = 1.5.dp, - color = colorScheme.outline.copy(alpha = 0.10f), - shape = RoundedCornerShape(20.dp), - ).clip(RoundedCornerShape(20.dp)), - ) { - SettingsItem( - icon = Lucide.Info, - iconTint = colorScheme.primary, - title = "About", - description = "Version and project info", - onClick = { navController.navigate(AboutScreen) }, - ) - HorizontalDivider( - thickness = 1.dp, - color = colorScheme.outline.copy(alpha = 0.06f), - ) - SettingsItem( - icon = Lucide.ScrollText, - iconTint = DayGlowHistoryAccent, - title = "Logs", - description = "View application logs", - onClick = { navController.navigate(LogsScreen) }, - ) - HorizontalDivider( - thickness = 1.dp, - color = colorScheme.outline.copy(alpha = 0.06f), - ) - SettingsItem( - icon = Lucide.Palette, - iconTint = colorScheme.tertiary, - title = "Theme", - description = "Appearance and display", - onClick = { navController.navigate(ThemeScreen) }, - ) - } - } - } -} - -@Composable -private fun SettingsItem( - icon: ImageVector, - iconTint: Color, - title: String, - description: String, - onClick: () -> Unit, -) { - val colorScheme = MaterialTheme.colorScheme - - Row( - modifier = Modifier - .fillMaxWidth() - .clickable(onClick = onClick) - .padding(horizontal = 16.dp, vertical = 14.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - Box( - modifier = Modifier - .size(44.dp) - .clip(RoundedCornerShape(14.dp)) - .background(iconTint.copy(alpha = 0.08f)) - .border( - width = 1.dp, - color = iconTint.copy(alpha = 0.12f), - shape = RoundedCornerShape(14.dp), - ), - contentAlignment = Alignment.Center, - ) { - Icon( - imageVector = icon, - contentDescription = title, - tint = iconTint, - modifier = Modifier.size(20.dp), - ) - } - Spacer(modifier = Modifier.width(14.dp)) - Column { - Text( - text = title, - color = colorScheme.onSurface, - fontFamily = inter, - fontSize = 15.sp, - ) - Spacer(modifier = Modifier.height(2.dp)) - Text( - text = description, - color = colorScheme.onSurface.copy(alpha = 0.5f), - fontFamily = inter, - fontSize = 12.sp, - ) - } - } -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/ThemeScreen.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/ThemeScreen.kt deleted file mode 100644 index 1827e3f..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/ThemeScreen.kt +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.ui.screens.settings - -import androidx.compose.foundation.background -import androidx.compose.foundation.border -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.navigation.NavController -import com.composables.icons.lucide.Check -import com.composables.icons.lucide.Lucide -import com.composables.icons.lucide.Moon -import com.composables.icons.lucide.Sun -import org.bitcoindevkit.devkitwallet.presentation.theme.inter -import org.bitcoindevkit.devkitwallet.presentation.ui.components.SecondaryScreensAppBar - -@Composable -internal fun ThemeScreen(useDarkTheme: Boolean, onToggleTheme: () -> Unit, navController: NavController) { - val colorScheme = MaterialTheme.colorScheme - - Scaffold( - topBar = { - SecondaryScreensAppBar( - title = "Theme", - navigation = { navController.popBackStack() }, - ) - }, - containerColor = colorScheme.surface, - ) { paddingValues -> - Column( - modifier = Modifier - .fillMaxSize() - .padding(paddingValues) - .padding(horizontal = 20.dp, vertical = 16.dp), - ) { - Column( - modifier = Modifier - .fillMaxWidth() - .border( - width = 1.5.dp, - color = colorScheme.outline.copy(alpha = 0.10f), - shape = RoundedCornerShape(20.dp), - ).clip(RoundedCornerShape(20.dp)), - ) { - ThemeItem( - icon = Lucide.Sun, - iconTint = colorScheme.primary, - title = "DayGlow", - description = "Light theme", - isSelected = !useDarkTheme, - onClick = { if (useDarkTheme) onToggleTheme() }, - ) - HorizontalDivider( - thickness = 1.dp, - color = colorScheme.outline.copy(alpha = 0.06f), - ) - ThemeItem( - icon = Lucide.Moon, - iconTint = colorScheme.secondary, - title = "NightGlow", - description = "Dark theme", - isSelected = useDarkTheme, - onClick = { if (!useDarkTheme) onToggleTheme() }, - ) - } - } - } -} - -@Composable -private fun ThemeItem( - icon: ImageVector, - iconTint: Color, - title: String, - description: String, - isSelected: Boolean, - onClick: () -> Unit, -) { - val colorScheme = MaterialTheme.colorScheme - - Row( - modifier = Modifier - .fillMaxWidth() - .clickable(onClick = onClick) - .padding(horizontal = 16.dp, vertical = 14.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - Box( - modifier = Modifier - .size(44.dp) - .clip(RoundedCornerShape(14.dp)) - .background(iconTint.copy(alpha = if (isSelected) 0.10f else 0.05f)) - .border( - width = 1.dp, - color = iconTint.copy(alpha = if (isSelected) 0.15f else 0.07f), - shape = RoundedCornerShape(14.dp), - ), - contentAlignment = Alignment.Center, - ) { - Icon( - imageVector = icon, - contentDescription = title, - tint = if (isSelected) iconTint else iconTint.copy(alpha = 0.4f), - modifier = Modifier.size(20.dp), - ) - } - Spacer(modifier = Modifier.width(14.dp)) - Column(modifier = Modifier.weight(1f)) { - Text( - text = title, - color = if (isSelected) colorScheme.onSurface else colorScheme.onSurface.copy(alpha = 0.5f), - fontFamily = inter, - fontSize = 15.sp, - ) - Spacer(modifier = Modifier.height(2.dp)) - Text( - text = description, - color = colorScheme.onSurface.copy(alpha = 0.5f), - fontFamily = inter, - fontSize = 12.sp, - ) - } - if (isSelected) { - Icon( - imageVector = Lucide.Check, - contentDescription = "Selected", - tint = colorScheme.primary, - modifier = Modifier.size(18.dp), - ) - } else { - Spacer(modifier = Modifier.width(18.dp)) - } - } -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/RBFScreen.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/RBFScreen.kt deleted file mode 100644 index 0e77b91..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/RBFScreen.kt +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.ui.screens.wallet - -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.runtime.Composable -import androidx.compose.ui.unit.dp -import androidx.navigation.NavController - -private const val TAG = "RBFScreen" - -@Composable -internal fun RBFScreen( - txid: String?, - navController: NavController, - paddingValues: PaddingValues = PaddingValues(0.dp), -) { -// if (txid.isNullOrEmpty()) { -// navController.popBackStack() -// } -// var transaction: TransactionDetails? = getTransaction(txid = txid) -// if (transaction == null) { -// navController.popBackStack() -// } -// transaction = transaction as TransactionDetails -// val context = LocalContext.current -// -// val amount = (transaction.sent - transaction.received - (transaction.fee ?: 0UL)).toString() -// val feeRate: MutableState = rememberSaveable { mutableStateOf("") } -// val (showDialog, setShowDialog) = rememberSaveable { mutableStateOf(false) } -// -// ConstraintLayout( -// modifier = Modifier -// .fillMaxSize() -// .padding(paddingValues) -// .background(DevkitWalletColors.primary) -// ) { -// val (screenTitle, transactionInputs, bottomButtons) = createRefs() -// -// Text( -// text = "Send Bitcoin", -// color = DevkitWalletColors.white, -// fontSize = 28.sp, -// textAlign = TextAlign.Center, -// modifier = Modifier -// .constrainAs(screenTitle) { -// top.linkTo(parent.top) -// start.linkTo(parent.start) -// end.linkTo(parent.end) -// } -// .padding(top = 70.dp) -// ) -// -// Column( -// horizontalAlignment = Alignment.CenterHorizontally, -// verticalArrangement = Arrangement.Center, -// modifier = Modifier.constrainAs(transactionInputs) { -// top.linkTo(screenTitle.bottom) -// bottom.linkTo(bottomButtons.top) -// start.linkTo(parent.start) -// end.linkTo(parent.end) -// height = Dimension.fillToConstraints -// } -// ) { -// ShowTxnDetail(name = "Transaction Id",content = txid!!) -// ShowTxnDetail(name = "Amount", content = amount) -// TransactionFeeInput(feeRate = feeRate) -// BumpFeeDialog( -// txid = txid, -// amount = amount, -// feeRate = feeRate, -// showDialog = showDialog, -// setShowDialog = setShowDialog, -// context = context -// ) -// } -// Column( -// Modifier -// .constrainAs(bottomButtons) { -// bottom.linkTo(parent.bottom) -// start.linkTo(parent.start) -// end.linkTo(parent.end) -// } -// .padding(bottom = 32.dp) -// ) { -// Button( -// onClick = { setShowDialog(true) }, -// colors = ButtonDefaults.buttonColors(DevkitWalletColors.accent2), -// shape = RoundedCornerShape(16.dp), -// modifier = Modifier -// .height(80.dp) -// .fillMaxWidth(0.9f) -// .padding(vertical = 8.dp, horizontal = 8.dp) -// .shadow(elevation = 4.dp, shape = RoundedCornerShape(16.dp)) -// ) { -// Text( -// text = "broadcast transaction", -// fontSize = 14.sp, -// textAlign = TextAlign.Center, -// lineHeight = 28.sp, -// ) -// } -// Button( -// onClick = { navController.navigate(Screen.HomeScreen.route) }, -// colors = ButtonDefaults.buttonColors(DevkitWalletColors.primaryLight), -// shape = RoundedCornerShape(16.dp), -// modifier = Modifier -// .height(80.dp) -// .fillMaxWidth(0.9f) -// .padding(vertical = 8.dp, horizontal = 8.dp) -// .shadow(elevation = 4.dp, shape = RoundedCornerShape(16.dp)) -// ) { -// Text( -// text = "back to wallet", -// fontSize = 14.sp, -// textAlign = TextAlign.Center, -// lineHeight = 28.sp, -// ) -// } -// } -// } -} -// -// @OptIn(ExperimentalMaterial3Api::class) -// @Composable -// private fun ShowTxnDetail(name: String, content: String) { -// Row( -// verticalAlignment = Alignment.CenterVertically, -// modifier = Modifier.fillMaxWidth(fraction = 0.9f) -// ) { -// OutlinedTextField( -// modifier = Modifier -// .padding(vertical = 8.dp) -// .weight(0.5f), -// value = content, -// onValueChange = { }, -// label = { -// Text( -// text = name, -// color = DevkitWalletColors.white, -// ) -// }, -// singleLine = true, -// textStyle = TextStyle(color = DevkitWalletColors.white), -// colors = TextFieldDefaults.outlinedTextFieldColors( -// focusedBorderColor = DevkitWalletColors.accent1, -// unfocusedBorderColor = DevkitWalletColors.white, -// cursorColor = DevkitWalletColors.accent1, -// ), -// enabled = false, -// ) -// } -// } -// -// @OptIn(ExperimentalMaterial3Api::class) -// @Composable -// private fun TransactionFeeInput(feeRate: MutableState) { -// Column(horizontalAlignment = Alignment.CenterHorizontally) { -// OutlinedTextField( -// modifier = Modifier -// .padding(vertical = 8.dp) -// .fillMaxWidth(0.9f), -// value = feeRate.value, -// onValueChange = { newValue: String -> -// feeRate.value = newValue.filter { it.isDigit() } -// }, -// singleLine = true, -// textStyle = TextStyle(color = DevkitWalletColors.white), -// label = { -// Text( -// text = "New fee rate", -// color = DevkitWalletColors.white, -// ) -// }, -// colors = TextFieldDefaults.outlinedTextFieldColors( -// focusedBorderColor = DevkitWalletColors.accent1, -// unfocusedBorderColor = DevkitWalletColors.white, -// cursorColor = DevkitWalletColors.accent1, -// ), -// ) -// } -// } -// -// @Composable -// fun BumpFeeDialog( -// txid: String, -// amount: String, -// showDialog: Boolean, -// setShowDialog: (Boolean) -> Unit, -// context: Context, -// feeRate: MutableState, -// ) { -// if (showDialog) { -// var confirmationText = "Confirm Transaction : \nTxid : $txid\nAmount : $amount" -// if (feeRate.value.isNotEmpty()) { -// confirmationText += "Fee Rate : ${feeRate.value.toULong()}" -// } -// AlertDialog( -// containerColor = DevkitWalletColors.primaryLight, -// onDismissRequest = {}, -// title = { -// Text( -// text = "Confirm transaction", -// color = DevkitWalletColors.white -// ) -// }, -// text = { -// Text( -// text = confirmationText, -// color = DevkitWalletColors.white -// ) -// }, -// confirmButton = { -// TextButton( -// onClick = { -// if (feeRate.value.isNotEmpty()) { -// broadcastTransaction(txid = txid, feeRate = feeRate.value.toFloat()) -// } else { -// Toast.makeText(context, "Fee is empty!", Toast.LENGTH_SHORT).show() -// } -// setShowDialog(false) -// }, -// ) { -// Text( -// text = "Confirm", -// color = DevkitWalletColors.white -// ) -// } -// }, -// dismissButton = { -// TextButton( -// onClick = { -// setShowDialog(false) -// }, -// ) { -// Text( -// text = "Cancel", -// color = DevkitWalletColors.white -// ) -// } -// }, -// ) -// } -// } -// -// private fun broadcastTransaction(txid: String, feeRate: Float = 1F) { -// Log.i(TAG, "Attempting to broadcast transaction with inputs: txid $txid, fee rate: $feeRate") -// try { -// // create, sign, and broadcast -// val psbt: PartiallySignedTransaction = Wallet.createBumpFeeTransaction(txid = txid, feeRate = feeRate) -// Wallet.sign(psbt) -// val newTxid: String = Wallet.broadcast(psbt) -// Log.i(TAG, "Transaction was broadcast! txid: $newTxid") -// } catch (e: Throwable) { -// Log.i(TAG, "Broadcast error: ${e.message}") -// } -// } diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/ReceiveScreen.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/ReceiveScreen.kt deleted file mode 100644 index 9b8d70a..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/ReceiveScreen.kt +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.ui.screens.wallet - -import android.content.ClipData -import android.content.ClipboardManager -import android.content.Context -import android.util.Log -import androidx.compose.foundation.BorderStroke -import androidx.compose.foundation.Image -import androidx.compose.foundation.border -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedButton -import androidx.compose.material3.Scaffold -import androidx.compose.material3.SnackbarHost -import androidx.compose.material3.SnackbarHostState -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.ImageBitmap -import androidx.compose.ui.graphics.asImageBitmap -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.core.graphics.createBitmap -import androidx.navigation.NavController -import com.composables.icons.lucide.ClipboardCopy -import com.composables.icons.lucide.Lucide -import com.google.zxing.BarcodeFormat -import com.google.zxing.common.BitMatrix -import com.google.zxing.qrcode.QRCodeWriter -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import org.bitcoindevkit.devkitwallet.presentation.navigation.HomeScreen -import org.bitcoindevkit.devkitwallet.presentation.theme.googleSansCode -import org.bitcoindevkit.devkitwallet.presentation.theme.inter -import org.bitcoindevkit.devkitwallet.presentation.ui.components.SecondaryScreensAppBar -import org.bitcoindevkit.devkitwallet.presentation.viewmodels.mvi.ReceiveScreenAction -import org.bitcoindevkit.devkitwallet.presentation.viewmodels.mvi.ReceiveScreenState - -private const val TAG = "ReceiveScreen" - -@Composable -internal fun ReceiveScreen( - state: ReceiveScreenState, - onAction: (ReceiveScreenAction) -> Unit, - navController: NavController, -) { - Log.i(TAG, "We are recomposing the ReceiveScreen") - val snackbarHostState = remember { SnackbarHostState() } - val colorScheme = MaterialTheme.colorScheme - val context = LocalContext.current - val scope = rememberCoroutineScope() - - Scaffold( - snackbarHost = { SnackbarHost(snackbarHostState) }, - topBar = { - SecondaryScreensAppBar( - title = "Receive Address", - navigation = { navController.navigate(HomeScreen) }, - ) - }, - containerColor = colorScheme.surface, - ) { paddingValues -> - Column( - modifier = Modifier - .fillMaxSize() - .padding(paddingValues) - .verticalScroll(rememberScrollState()), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Spacer(Modifier.height(24.dp)) - - val qrBitmap: ImageBitmap? = state.address?.let { addressToQR(it) } - Log.i(TAG, "New receive address is ${state.address}") - - if (qrBitmap != null) { - // QR code in outlined container - Box( - modifier = Modifier - .border( - width = 1.5.dp, - color = colorScheme.outline.copy(alpha = 0.10f), - shape = RoundedCornerShape(24.dp), - ).clip(RoundedCornerShape(24.dp)) - .padding(20.dp), - contentAlignment = Alignment.Center, - ) { - Image( - bitmap = qrBitmap, - contentDescription = "Bitcoin address QR code", - Modifier - .size(230.dp) - .clip(RoundedCornerShape(12.dp)), - ) - } - - Spacer(Modifier.height(24.dp)) - - // Address card with copy button - Box( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 24.dp) - .border( - width = 1.5.dp, - color = colorScheme.outline.copy(alpha = 0.10f), - shape = RoundedCornerShape(16.dp), - ).clip(RoundedCornerShape(16.dp)) - .padding(horizontal = 16.dp, vertical = 14.dp), - ) { - Text( - text = state.address.chunked(4).joinToString(" "), - fontFamily = googleSansCode, - fontSize = 13.sp, - fontWeight = FontWeight.Light, - color = colorScheme.onSurface, - modifier = Modifier - .align(Alignment.CenterStart) - .padding(end = 40.dp), - ) - IconButton( - onClick = { - copyToClipboard( - state.address, - context, - scope, - snackbarHostState, - null, - ) - }, - modifier = Modifier - .size(28.dp) - .align(Alignment.CenterEnd), - ) { - Icon( - Lucide.ClipboardCopy, - tint = colorScheme.onSurface.copy(alpha = 0.5f), - contentDescription = "Copy to clipboard", - modifier = Modifier.size(18.dp), - ) - } - } - - Spacer(Modifier.height(24.dp)) - - // Address index - Text( - text = "Address index: ${state.addressIndex}", - fontFamily = inter, - fontSize = 12.sp, - color = colorScheme.onSurface.copy(alpha = 0.4f), - ) - } - - // Generate new address button - OutlinedButton( - onClick = { onAction(ReceiveScreenAction.UpdateAddress) }, - shape = RoundedCornerShape(16.dp), - border = BorderStroke(1.5.dp, colorScheme.primary), - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 24.dp) - .height(52.dp), - ) { - Text( - text = "Generate New Address", - fontFamily = inter, - fontSize = 15.sp, - color = colorScheme.primary, - ) - } - - Spacer(Modifier.height(32.dp)) - } - } -} - -private fun addressToQR(address: String): ImageBitmap? { - Log.i(TAG, "We are generating the QR code for address $address") - try { - val qrCodeWriter = QRCodeWriter() - val bitMatrix: BitMatrix = qrCodeWriter.encode(address, BarcodeFormat.QR_CODE, 1000, 1000) - val bitMap = createBitmap(1000, 1000) - for (x in 0 until 1000) { - for (y in 0 until 1000) { - bitMap.setPixel(x, y, if (bitMatrix[x, y]) 0xFF1C1B1F.toInt() else 0xFFE6E1E5.toInt()) - } - } - return bitMap.asImageBitmap() - } catch (e: Throwable) { - Log.i(TAG, "Error with QRCode generation, $e") - } - return null -} - -fun copyToClipboard( - content: String, - context: Context, - scope: CoroutineScope, - snackbarHostState: SnackbarHostState, - setCopyClicked: ( - (Boolean) -> Unit - )?, -) { - val clipboard: ClipboardManager = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager - val clip: ClipData = ClipData.newPlainText("", content) - clipboard.setPrimaryClip(clip) - scope.launch { - snackbarHostState.showSnackbar("Copied address to clipboard!") - delay(1000) - if (setCopyClicked != null) { - setCopyClicked(false) - } - } -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/SendScreen.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/SendScreen.kt deleted file mode 100644 index 12c4186..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/SendScreen.kt +++ /dev/null @@ -1,480 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.ui.screens.wallet - -import android.content.Context -import android.widget.Toast -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -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.material3.AlertDialog -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.OutlinedTextFieldDefaults -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Switch -import androidx.compose.material3.SwitchDefaults -import androidx.compose.material3.Text -import androidx.compose.material3.TextButton -import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.mutableStateListOf -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.navigation.NavController -import org.bitcoindevkit.devkitwallet.presentation.navigation.HomeScreen -import org.bitcoindevkit.devkitwallet.presentation.theme.inter -import org.bitcoindevkit.devkitwallet.presentation.ui.components.SecondaryScreensAppBar -import org.bitcoindevkit.devkitwallet.presentation.viewmodels.SendViewModel -import org.bitcoindevkit.devkitwallet.presentation.viewmodels.mvi.Recipient -import org.bitcoindevkit.devkitwallet.presentation.viewmodels.mvi.SendScreenAction -import org.bitcoindevkit.devkitwallet.presentation.viewmodels.mvi.TransactionType -import org.bitcoindevkit.devkitwallet.presentation.viewmodels.mvi.TxDataBundle - -private const val TAG = "SendScreen" - -@Composable -internal fun SendScreen(navController: NavController, sendViewModel: SendViewModel) { - val onAction = sendViewModel::onAction - val context = LocalContext.current - val colorScheme = MaterialTheme.colorScheme - - val recipientList: MutableList = remember { mutableStateListOf(Recipient(address = "", amount = 0u)) } - val feeRate: MutableState = rememberSaveable { mutableStateOf("") } - val (showDialog, setShowDialog) = rememberSaveable { mutableStateOf(false) } - - val sendAll: MutableState = remember { mutableStateOf(false) } - val opReturnMsg: MutableState = remember { mutableStateOf(null) } - val (showAdvanced, setShowAdvanced) = rememberSaveable { mutableStateOf(false) } - - val textFieldColors = OutlinedTextFieldDefaults.colors( - focusedBorderColor = colorScheme.primary, - unfocusedBorderColor = colorScheme.outline.copy(alpha = 0.30f), - cursorColor = colorScheme.primary, - focusedLabelColor = colorScheme.primary, - unfocusedLabelColor = colorScheme.onSurface.copy(alpha = 0.5f), - ) - - Scaffold( - topBar = { - SecondaryScreensAppBar( - title = "Send Bitcoin", - navigation = { navController.navigate(HomeScreen) }, - ) - }, - containerColor = colorScheme.surface, - ) { paddingValues -> - Column( - modifier = Modifier - .fillMaxSize() - .padding(paddingValues) - .verticalScroll(rememberScrollState()) - .padding(horizontal = 24.dp), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Spacer(Modifier.height(16.dp)) - - // Recipient address fields - recipientList.forEachIndexed { index, _ -> - val recipientAddress: MutableState = rememberSaveable { mutableStateOf("") } - - FormLabel(text = "Recipient address${if (recipientList.size > 1) " ${index + 1}" else ""}") - OutlinedTextField( - modifier = Modifier.fillMaxWidth(), - value = recipientAddress.value, - onValueChange = { - recipientAddress.value = it - recipientList[index].address = it - }, - placeholder = { - Text( - text = "bc1q...", - color = colorScheme.onSurface.copy(alpha = 0.3f), - fontFamily = inter, - ) - }, - singleLine = true, - textStyle = TextStyle( - color = colorScheme.onSurface, - fontFamily = inter, - fontSize = 15.sp, - ), - colors = textFieldColors, - shape = RoundedCornerShape(12.dp), - ) - Spacer(Modifier.height(16.dp)) - } - - // Amount fields - recipientList.forEachIndexed { index, _ -> - val amount: MutableState = rememberSaveable { mutableStateOf("") } - val transactionType = if (sendAll.value) TransactionType.SEND_ALL else TransactionType.STANDARD - - FormLabel( - text = when { - transactionType == TransactionType.SEND_ALL -> "Amount (Send All)" - recipientList.size > 1 -> "Amount ${index + 1}" - else -> "Amount" - } - ) - OutlinedTextField( - modifier = Modifier.fillMaxWidth(), - value = amount.value, - onValueChange = { - amount.value = it - recipientList[index].amount = it.toULongOrNull() ?: 0u - }, - trailingIcon = { - Text( - text = "sats", - color = colorScheme.onSurface.copy(alpha = 0.4f), - fontFamily = inter, - fontSize = 13.sp, - modifier = Modifier.padding(end = 8.dp), - ) - }, - singleLine = true, - textStyle = TextStyle( - color = colorScheme.onSurface, - fontFamily = inter, - fontSize = 15.sp, - ), - colors = textFieldColors, - shape = RoundedCornerShape(12.dp), - enabled = transactionType != TransactionType.SEND_ALL, - ) - Spacer(Modifier.height(16.dp)) - } - - // Fee rate - FormLabel(text = "Fee rate") - OutlinedTextField( - modifier = Modifier.fillMaxWidth(), - value = feeRate.value, - onValueChange = { newValue: String -> - feeRate.value = newValue.filter { it.isDigit() } - }, - trailingIcon = { - Text( - text = "sat/vB", - color = colorScheme.onSurface.copy(alpha = 0.4f), - fontFamily = inter, - fontSize = 13.sp, - modifier = Modifier.padding(end = 8.dp), - ) - }, - singleLine = true, - textStyle = TextStyle( - color = colorScheme.onSurface, - fontFamily = inter, - fontSize = 15.sp, - ), - colors = textFieldColors, - shape = RoundedCornerShape(12.dp), - ) - Text( - text = "Suggested: 1–10 for low priority", - color = colorScheme.onSurface.copy(alpha = 0.35f), - fontFamily = inter, - fontSize = 12.sp, - modifier = Modifier - .fillMaxWidth() - .padding(start = 4.dp, top = 4.dp), - ) - - Spacer(Modifier.height(20.dp)) - - // Advanced options toggle - TextButton( - onClick = { setShowAdvanced(!showAdvanced) }, - ) { - Text( - text = if (showAdvanced) "Hide advanced options" else "Advanced options", - color = colorScheme.primary, - fontFamily = inter, - fontSize = 14.sp, - ) - } - - AnimatedVisibility(visible = showAdvanced) { - Column( - modifier = Modifier.fillMaxWidth(), - ) { - Spacer(Modifier.height(8.dp)) - - // Send all switch - Row( - modifier = Modifier.fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween, - ) { - Text( - text = "Send All", - color = colorScheme.onSurface, - fontFamily = inter, - fontSize = 15.sp, - ) - Switch( - checked = sendAll.value, - onCheckedChange = { - sendAll.value = !sendAll.value - while (recipientList.size > 1) { - recipientList.removeAt(recipientList.lastIndex) - } - }, - colors = SwitchDefaults.colors( - uncheckedBorderColor = colorScheme.outline.copy(alpha = 0.30f), - uncheckedThumbColor = colorScheme.outline, - uncheckedTrackColor = colorScheme.surface, - checkedThumbColor = colorScheme.surface, - checkedTrackColor = colorScheme.primary, - ), - ) - } - - Spacer(Modifier.height(12.dp)) - - // OP_RETURN message - FormLabel(text = "OP_RETURN message (optional)") - OutlinedTextField( - modifier = Modifier.fillMaxWidth(), - value = opReturnMsg.value ?: "", - onValueChange = { opReturnMsg.value = it }, - singleLine = true, - textStyle = TextStyle( - color = colorScheme.onSurface, - fontFamily = inter, - fontSize = 15.sp, - ), - colors = textFieldColors, - shape = RoundedCornerShape(12.dp), - ) - - Spacer(Modifier.height(16.dp)) - - // Number of recipients - Text( - text = "Number of Recipients", - color = colorScheme.onSurface, - fontFamily = inter, - fontSize = 14.sp, - modifier = Modifier.fillMaxWidth(), - ) - Spacer(Modifier.height(8.dp)) - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically, - ) { - Button( - onClick = { - if (recipientList.size > 1) { - recipientList.removeAt(recipientList.lastIndex) - } - }, - enabled = !sendAll.value, - colors = ButtonDefaults.buttonColors( - containerColor = colorScheme.secondary, - ), - shape = RoundedCornerShape(12.dp), - modifier = Modifier.width(70.dp), - ) { - Text(text = "−", fontSize = 18.sp) - } - - Text( - text = "${recipientList.size}", - color = colorScheme.onSurface, - fontFamily = inter, - fontSize = 18.sp, - ) - - Button( - onClick = { recipientList.add(Recipient("", 0u)) }, - enabled = !sendAll.value, - colors = ButtonDefaults.buttonColors( - containerColor = colorScheme.primary, - ), - shape = RoundedCornerShape(12.dp), - modifier = Modifier.width(70.dp), - ) { - Text(text = "+", fontSize = 18.sp) - } - } - - Spacer(Modifier.height(16.dp)) - } - } - - Spacer(Modifier.height(24.dp)) - - // Broadcast button - Button( - onClick = { setShowDialog(true) }, - colors = ButtonDefaults.buttonColors( - containerColor = colorScheme.secondary, - ), - shape = RoundedCornerShape(16.dp), - modifier = Modifier - .fillMaxWidth() - .height(52.dp), - ) { - Text( - text = "Broadcast Transaction", - fontFamily = inter, - fontSize = 15.sp, - ) - } - - Spacer(Modifier.height(32.dp)) - } - - // Confirmation dialog - ConfirmDialog( - recipientList = recipientList, - feeRate = feeRate, - showDialog = showDialog, - setShowDialog = setShowDialog, - transactionType = if (sendAll.value) TransactionType.SEND_ALL else TransactionType.STANDARD, - opReturnMsg = opReturnMsg.value, - context = context, - onAction = onAction, - ) - } -} - -@Composable -private fun FormLabel(text: String) { - val colorScheme = MaterialTheme.colorScheme - Text( - text = text, - color = colorScheme.onSurface.copy(alpha = 0.6f), - fontFamily = inter, - fontSize = 13.sp, - modifier = Modifier - .fillMaxWidth() - .padding(bottom = 6.dp), - ) -} - -fun checkRecipientList( - recipientList: MutableList, - feeRate: MutableState, - context: Context, -): Boolean { - if (recipientList.size > 4) { - Toast.makeText(context, "Too many recipients", Toast.LENGTH_SHORT).show() - return false - } - for (recipient in recipientList) { - if (recipient.address == "") { - Toast.makeText(context, "Address is empty", Toast.LENGTH_SHORT).show() - return false - } - } - if (feeRate.value.isBlank()) { - Toast.makeText(context, "Fee rate is empty", Toast.LENGTH_SHORT).show() - return false - } - return true -} - -@Composable -private fun ConfirmDialog( - recipientList: MutableList, - feeRate: MutableState, - showDialog: Boolean, - setShowDialog: (Boolean) -> Unit, - transactionType: TransactionType, - opReturnMsg: String?, - context: Context, - onAction: (SendScreenAction) -> Unit, -) { - if (showDialog) { - val colorScheme = MaterialTheme.colorScheme - - var confirmationText = "Confirm Transaction:\n" - recipientList.forEach { confirmationText += "${it.address}, ${it.amount}\n" } - if (feeRate.value.isNotEmpty()) { - confirmationText += "Fee Rate: ${feeRate.value.toULong()}\n" - } - if (!opReturnMsg.isNullOrEmpty()) { - confirmationText += "OP_RETURN Message: $opReturnMsg" - } - AlertDialog( - containerColor = colorScheme.surface, - onDismissRequest = {}, - title = { - Text( - text = "Confirm transaction", - color = colorScheme.onSurface, - fontFamily = inter, - ) - }, - text = { - Text( - text = confirmationText, - color = colorScheme.onSurface.copy(alpha = 0.7f), - fontFamily = inter, - fontSize = 14.sp, - ) - }, - confirmButton = { - TextButton( - onClick = { - if (checkRecipientList(recipientList = recipientList, feeRate = feeRate, context = context)) { - val txDataBundle = - TxDataBundle( - recipients = recipientList.toList(), - feeRate = feeRate.value.toULong(), - transactionType = transactionType, - opReturnMsg = opReturnMsg, - ) - onAction(SendScreenAction.Broadcast(txDataBundle)) - setShowDialog(false) - } - }, - ) { - Text( - text = "Confirm", - color = colorScheme.primary, - fontFamily = inter, - ) - } - }, - dismissButton = { - TextButton( - onClick = { setShowDialog(false) }, - ) { - Text( - text = "Cancel", - color = colorScheme.onSurface.copy(alpha = 0.5f), - fontFamily = inter, - ) - } - }, - ) - } -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/TransactionHistoryScreen.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/TransactionHistoryScreen.kt deleted file mode 100644 index dbbfd51..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/TransactionHistoryScreen.kt +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.ui.screens.wallet - -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Scaffold -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import androidx.navigation.NavController -import org.bitcoindevkit.devkitwallet.domain.Wallet -import org.bitcoindevkit.devkitwallet.presentation.navigation.HomeScreen -import org.bitcoindevkit.devkitwallet.presentation.navigation.TransactionScreen -import org.bitcoindevkit.devkitwallet.presentation.ui.components.ConfirmedTransactionCard -import org.bitcoindevkit.devkitwallet.presentation.ui.components.PendingTransactionCard -import org.bitcoindevkit.devkitwallet.presentation.ui.components.SecondaryScreensAppBar - -private const val TAG = "TransactionHistoryScreen" - -@Composable -internal fun TransactionHistoryScreen(navController: NavController, activeWallet: Wallet) { - val (pendingTransactions, confirmedTransactions) = activeWallet.getAllTxDetails().partition { it.pending } - - Scaffold( - topBar = { - SecondaryScreensAppBar( - title = "Transaction History", - navigation = { navController.navigate(HomeScreen) }, - ) - }, - containerColor = MaterialTheme.colorScheme.surface, - ) { paddingValues -> - val scrollState = rememberScrollState() - Column( - modifier = - Modifier - .padding(paddingValues) - .fillMaxSize() - .padding(top = 6.dp) - .verticalScroll(state = scrollState), - ) { - if (pendingTransactions.isNotEmpty()) { - pendingTransactions.forEach { - PendingTransactionCard(details = it, navController = navController) - } - } - if (confirmedTransactions.isNotEmpty()) { - confirmedTransactions.sortedBy { it.confirmationBlock?.height }.forEach { - ConfirmedTransactionCard(it, navController) - } - } - } - } -} - -fun viewTransaction(navController: NavController, txid: String) { - navController.navigate(TransactionScreen(txid)) -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/TransactionScreen.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/TransactionScreen.kt deleted file mode 100644 index 2c2a8e5..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/TransactionScreen.kt +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.ui.screens.wallet - -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.navigation.NavController -import org.bitcoindevkit.devkitwallet.presentation.navigation.RbfScreen -import org.bitcoindevkit.devkitwallet.presentation.theme.inter -import org.bitcoindevkit.devkitwallet.presentation.ui.components.SecondaryScreensAppBar - -@Composable -internal fun TransactionScreen(txid: String?, navController: NavController) { - val colorScheme = MaterialTheme.colorScheme - - Scaffold( - topBar = { - SecondaryScreensAppBar( - title = "Transaction Details", - navigation = { navController.navigateUp() }, - ) - }, - containerColor = colorScheme.surface, - ) { paddingValues -> - Column( - modifier = - Modifier - .fillMaxSize() - .padding(paddingValues) - .verticalScroll(rememberScrollState()) - .padding(horizontal = 24.dp), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Spacer(Modifier.height(48.dp)) - - Text( - text = "Transaction", - color = colorScheme.onSurface, - fontSize = 28.sp, - fontFamily = inter, - textAlign = TextAlign.Center, - modifier = Modifier.fillMaxWidth(), - ) - - Spacer(Modifier.weight(1f)) - - TransactionDetailButton( - content = "increase fees", - navController = navController, - txid = txid, - ) - - Spacer(Modifier.height(32.dp)) - } - } -} - -@Composable -fun TransactionDetailButton(content: String, navController: NavController, txid: String?) { - val colorScheme = MaterialTheme.colorScheme - Button( - onClick = { - when (content) { - "increase fees" -> { - navController.navigate(RbfScreen(txid!!)) - } - - "back to transaction list" -> { - navController.navigateUp() - } - } - }, - colors = ButtonDefaults.buttonColors(colorScheme.secondary), - shape = RoundedCornerShape(16.dp), - modifier = - Modifier - .height(52.dp) - .fillMaxWidth(), - ) { - Text( - text = content, - fontSize = 14.sp, - fontFamily = inter, - textAlign = TextAlign.Center, - ) - } -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/WalletHomeScreen.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/WalletHomeScreen.kt deleted file mode 100644 index 72ceeeb..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/WalletHomeScreen.kt +++ /dev/null @@ -1,414 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.ui.screens.wallet - -import android.content.Context -import android.net.ConnectivityManager -import android.net.NetworkCapabilities -import android.util.Log -import androidx.compose.foundation.BorderStroke -import androidx.compose.foundation.background -import androidx.compose.foundation.border -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.CardDefaults -import androidx.compose.material3.CenterAlignedTopAppBar -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedCard -import androidx.compose.material3.Scaffold -import androidx.compose.material3.SnackbarHost -import androidx.compose.material3.SnackbarHostState -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.navigation.NavHostController -import com.composables.icons.lucide.ArrowDownLeft -import com.composables.icons.lucide.ArrowUpRight -import com.composables.icons.lucide.History -import com.composables.icons.lucide.List -import com.composables.icons.lucide.Lucide -import com.composables.icons.lucide.Monitor -import com.composables.icons.lucide.Settings -import com.composables.icons.lucide.Shield -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.launch -import org.bitcoindevkit.devkitwallet.domain.CurrencyUnit -import org.bitcoindevkit.devkitwallet.domain.utils.formatInBtc -import org.bitcoindevkit.devkitwallet.presentation.navigation.BlockchainClientScreen -import org.bitcoindevkit.devkitwallet.presentation.navigation.ReceiveScreen -import org.bitcoindevkit.devkitwallet.presentation.navigation.RecoveryPhraseScreen -import org.bitcoindevkit.devkitwallet.presentation.navigation.SendScreen -import org.bitcoindevkit.devkitwallet.presentation.navigation.SettingsScreen -import org.bitcoindevkit.devkitwallet.presentation.navigation.TransactionHistoryScreen -import org.bitcoindevkit.devkitwallet.presentation.theme.DayGlowHistoryAccent -import org.bitcoindevkit.devkitwallet.presentation.theme.NightGlowSubtle -import org.bitcoindevkit.devkitwallet.presentation.theme.inter -import org.bitcoindevkit.devkitwallet.presentation.ui.components.CustomSnackbar -import org.bitcoindevkit.devkitwallet.presentation.viewmodels.mvi.WalletScreenAction -import org.bitcoindevkit.devkitwallet.presentation.viewmodels.mvi.WalletScreenState - -private const val TAG = "WalletHomeScreen" - -@Composable -internal fun WalletHomeScreen( - state: WalletScreenState, - onAction: (WalletScreenAction) -> Unit, - navController: NavHostController, -) { - val snackbarHostState = remember { SnackbarHostState() } - val networkAvailable: Boolean = isOnline(LocalContext.current) - val interactionSource = remember { MutableInteractionSource() } - val scope: CoroutineScope = rememberCoroutineScope() - val colorScheme = MaterialTheme.colorScheme - - LaunchedEffect(Unit) { - onAction(WalletScreenAction.UpdateBalance) - } - - Scaffold( - topBar = { WalletAppBar(onSettingsClick = { navController.navigate(SettingsScreen) }) }, - snackbarHost = { - SnackbarHost(hostState = snackbarHostState) { data -> - CustomSnackbar(data) - } - }, - ) { paddingValues -> - - // If a new snackbar has be triggered, show it - state.snackbarMessage?.let { message -> - Log.i("WalletHomeScreen", "Showing snackbar: $message") - LaunchedEffect(message) { - scope.launch { - snackbarHostState.showSnackbar(message) - onAction(WalletScreenAction.ClearSnackbar) - } - } - } - - Column( - modifier = - Modifier - .fillMaxSize() - .padding(paddingValues) - .clickable( - interactionSource = interactionSource, - indication = null, - onClick = { onAction(WalletScreenAction.SwitchUnit) }, - ), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Spacer(Modifier.height(32.dp)) - - // Balance - when (state.unit) { - CurrencyUnit.Bitcoin -> { - Text( - text = state.balance.formatInBtc(), - fontFamily = inter, - // fontFamily = googleSansCode, - fontSize = 48.sp, - fontWeight = FontWeight.Light, - color = colorScheme.onSurface, - ) - } - - CurrencyUnit.Satoshi -> { - Text( - text = "${state.balance} sat", - fontFamily = inter, - // fontFamily = googleSansCode, - fontSize = 48.sp, - fontWeight = FontWeight.Light, - color = colorScheme.onSurface, - ) - } - } - Text( - text = "BITCOIN", - fontSize = 14.sp, - color = NightGlowSubtle, - letterSpacing = 2.sp, - ) - - Spacer(Modifier.height(24.dp)) - - // Receive / Send row - Row( - modifier = Modifier.fillMaxWidth(0.9f), - horizontalArrangement = Arrangement.spacedBy(12.dp), - ) { - // Receive card - OutlinedCard( - onClick = { navController.navigate(ReceiveScreen) }, - modifier = Modifier - .weight(1f) - .height(120.dp), - shape = RoundedCornerShape(24.dp), - border = BorderStroke(1.5.dp, colorScheme.outline.copy(alpha = 0.15f)), - colors = CardDefaults.outlinedCardColors( - containerColor = Color.Transparent, - ), - ) { - Column( - modifier = Modifier - .fillMaxSize() - .padding(16.dp), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Box( - modifier = Modifier - .size(52.dp) - .clip(RoundedCornerShape(16.dp)) - .background(colorScheme.onSurfaceVariant.copy(alpha = 0.08f)) - .border( - width = 1.dp, - color = colorScheme.onSurfaceVariant.copy(alpha = 0.12f), - shape = RoundedCornerShape(16.dp), - ), - contentAlignment = Alignment.Center, - ) { - Icon( - imageVector = Lucide.ArrowDownLeft, - contentDescription = "Receive", - tint = colorScheme.onSurfaceVariant, - modifier = Modifier.size(24.dp), - ) - } - Spacer(Modifier.height(8.dp)) - Text( - text = "RECEIVE", - color = colorScheme.onSurfaceVariant, - fontSize = 12.sp, - fontWeight = FontWeight.Medium, - letterSpacing = 1.sp, - ) - } - } - - // Send card - OutlinedCard( - onClick = { navController.navigate(SendScreen) }, - enabled = networkAvailable, - modifier = Modifier - .weight(1f) - .height(120.dp), - shape = RoundedCornerShape(24.dp), - border = BorderStroke(1.5.dp, colorScheme.outline.copy(alpha = 0.15f)), - colors = CardDefaults.outlinedCardColors( - containerColor = Color.Transparent, - ), - ) { - Column( - modifier = Modifier - .fillMaxSize() - .padding(16.dp), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Box( - modifier = Modifier - .size(52.dp) - .clip(RoundedCornerShape(16.dp)) - .background(colorScheme.onSurfaceVariant.copy(alpha = 0.08f)) - .border( - width = 1.dp, - color = colorScheme.onSurfaceVariant.copy(alpha = 0.12f), - shape = RoundedCornerShape(16.dp), - ), - contentAlignment = Alignment.Center, - ) { - Icon( - imageVector = Lucide.ArrowUpRight, - contentDescription = "Send", - tint = colorScheme.onSurfaceVariant, - modifier = Modifier.size(24.dp), - ) - } - Spacer(Modifier.height(8.dp)) - Text( - text = "SEND", - color = colorScheme.onSurfaceVariant, - fontSize = 12.sp, - fontWeight = FontWeight.Medium, - letterSpacing = 1.sp, - ) - } - } - } - - Spacer(Modifier.height(16.dp)) - HorizontalDivider( - thickness = 1.dp, - color = colorScheme.outline.copy(alpha = 0.08f), - modifier = Modifier.fillMaxWidth(0.9f), - ) - Spacer(Modifier.height(16.dp)) - - // Quick actions row - Row( - horizontalArrangement = Arrangement.spacedBy(12.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - QuickAction( - icon = Lucide.List, - label = "UTXOs", - tint = colorScheme.primary, - onClick = {}, - ) - QuickAction( - icon = Lucide.Shield, - label = "Security", - tint = colorScheme.secondary, - onClick = { navController.navigate(RecoveryPhraseScreen) }, - ) - QuickAction( - icon = Lucide.Monitor, - label = "Node", - tint = colorScheme.tertiary, - onClick = { navController.navigate(BlockchainClientScreen) }, - ) - QuickAction( - icon = Lucide.History, - label = "History", - tint = DayGlowHistoryAccent, - onClick = { navController.navigate(TransactionHistoryScreen) }, - ) - } - - // Network unavailable banner - if (!networkAvailable) { - Spacer(Modifier.height(16.dp)) - Row( - Modifier - .fillMaxWidth() - .background(color = colorScheme.primary.copy(alpha = 0.12f)) - .height(40.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.Center, - ) { - Text( - text = "Network unavailable", - fontFamily = inter, - fontSize = 14.sp, - color = colorScheme.onSurface, - ) - } - } - } - } -} - -@Composable -private fun QuickAction(icon: ImageVector, label: String, tint: Color, onClick: () -> Unit) { - Column( - horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier - .clickable(onClick = onClick) - .padding(horizontal = 4.dp), - ) { - Box( - modifier = Modifier - .size(56.dp) - .border( - width = 1.5.dp, - color = tint.copy(alpha = 0.20f), - shape = CircleShape, - ), - contentAlignment = Alignment.Center, - ) { - Icon( - imageVector = icon, - contentDescription = label, - tint = tint, - modifier = Modifier.size(22.dp), - ) - } - Spacer(Modifier.height(4.dp)) - Text( - text = label, - fontSize = 11.sp, - color = NightGlowSubtle, - ) - } -} - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -internal fun WalletAppBar(onSettingsClick: () -> Unit) { - CenterAlignedTopAppBar( - title = { - Text( - text = "", - color = MaterialTheme.colorScheme.onSurface, - fontFamily = inter, - fontSize = 20.sp, - ) - }, - actions = { - IconButton(onClick = onSettingsClick) { - Icon( - imageVector = Lucide.Settings, - contentDescription = "Settings", - tint = MaterialTheme.colorScheme.onSurfaceVariant, - ) - } - }, - ) -} - -fun isOnline(context: Context): Boolean { - val connectivityManager = - context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager - val capabilities = - connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork) - if (capabilities != null) { - when { - capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> { - Log.i("Internet", "NetworkCapabilities.TRANSPORT_CELLULAR") - return true - } - - capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> { - Log.i("Internet", "NetworkCapabilities.TRANSPORT_WIFI") - return true - } - - capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> { - Log.i("Internet", "NetworkCapabilities.TRANSPORT_ETHERNET") - return true - } - } - } - return false -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/AddressViewModel.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/AddressViewModel.kt deleted file mode 100644 index e9e4a83..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/AddressViewModel.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.viewmodels - -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue -import androidx.lifecycle.ViewModel -import org.bitcoindevkit.AddressInfo -import org.bitcoindevkit.devkitwallet.domain.DwLogger -import org.bitcoindevkit.devkitwallet.domain.DwLogger.LogLevel.INFO -import org.bitcoindevkit.devkitwallet.domain.Wallet -import org.bitcoindevkit.devkitwallet.presentation.viewmodels.mvi.ReceiveScreenAction -import org.bitcoindevkit.devkitwallet.presentation.viewmodels.mvi.ReceiveScreenState - -internal class AddressViewModel(private val wallet: Wallet) : ViewModel() { - var state: ReceiveScreenState by mutableStateOf(ReceiveScreenState()) - private set - - fun onAction(action: ReceiveScreenAction) { - when (action) { - is ReceiveScreenAction.UpdateAddress -> updateAddress() - } - } - - private fun updateAddress() { - val newAddress: AddressInfo = wallet.getNewAddress() - DwLogger.log(INFO, "Revealing new address at index ${newAddress.index}") - - state = - ReceiveScreenState( - address = newAddress.address.toString(), - addressIndex = newAddress.index, - ) - } -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/SendViewModel.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/SendViewModel.kt deleted file mode 100644 index 3a0a345..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/SendViewModel.kt +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.viewmodels - -import android.util.Log -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import kotlinx.coroutines.launch -import org.bitcoindevkit.FeeRate -import org.bitcoindevkit.Psbt -import org.bitcoindevkit.devkitwallet.data.Kyoto -import org.bitcoindevkit.devkitwallet.data.KyotoNotInitialized -import org.bitcoindevkit.devkitwallet.domain.Wallet -import org.bitcoindevkit.devkitwallet.presentation.viewmodels.mvi.SendScreenAction -import org.bitcoindevkit.devkitwallet.presentation.viewmodels.mvi.TransactionType -import org.bitcoindevkit.devkitwallet.presentation.viewmodels.mvi.TxDataBundle - -private const val TAG = "SendViewModel" - -internal class SendViewModel(private val wallet: Wallet) : ViewModel() { - fun onAction(action: SendScreenAction) { - when (action) { - is SendScreenAction.Broadcast -> broadcast(action.txDataBundle) - } - } - - private fun broadcast(txInfo: TxDataBundle) { - Log.i(TAG, "The tx data bundle is $txInfo") - - // TODO: Add error snackbar if Kyoto node is not running, or maybe simply disable the button - viewModelScope.launch { - try { - // Create, sign, and broadcast - val psbt: Psbt = - when (txInfo.transactionType) { - TransactionType.STANDARD -> { - wallet.createTransaction( - recipientList = txInfo.recipients, - feeRate = FeeRate.fromSatPerVb(txInfo.feeRate), - opReturnMsg = txInfo.opReturnMsg, - ) - } - - // TransactionType.SEND_ALL -> Wallet.createSendAllTransaction(recipientList[0].address, FeeRate.fromSatPerVb(feeRate), rbfEnabled, opReturnMsg) - TransactionType.SEND_ALL -> { - throw NotImplementedError("Send all not implemented") - } - } - val isSigned = wallet.sign(psbt) - if (isSigned) { - val transaction = psbt.extractTx() - val wtxid: String = Kyoto.getInstance().broadcast(transaction).toString() - Log.i(TAG, "Transaction was broadcast! txid: $wtxid") - } else { - Log.i(TAG, "Transaction not signed.") - } - } catch (e: KyotoNotInitialized) { - Log.i(TAG, "Kyoto was not initialized! Transaction cannot be broadcast.") - } catch (e: Throwable) { - Log.i(TAG, "Broadcast error message: ${e.message}") - } - } - } -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/WalletViewModel.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/WalletViewModel.kt deleted file mode 100644 index 4ebc587..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/WalletViewModel.kt +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.viewmodels - -import android.util.Log -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import org.bitcoindevkit.devkitwallet.data.Kyoto -import org.bitcoindevkit.devkitwallet.domain.CurrencyUnit -import org.bitcoindevkit.devkitwallet.domain.DwLogger -import org.bitcoindevkit.devkitwallet.domain.DwLogger.LogLevel.INFO -import org.bitcoindevkit.devkitwallet.domain.Wallet -import org.bitcoindevkit.devkitwallet.presentation.viewmodels.mvi.WalletScreenAction -import org.bitcoindevkit.devkitwallet.presentation.viewmodels.mvi.WalletScreenState - -private const val TAG = "WalletViewModel" - -internal class WalletViewModel( - private val wallet: Wallet, -) : ViewModel() { - var state: WalletScreenState by mutableStateOf(WalletScreenState()) - private set - - private val kyotoCoroutineScope: CoroutineScope = CoroutineScope(Dispatchers.IO) - private var kyoto: Kyoto? = null - - @Suppress("ktlint:standard:no-multi-spaces") - fun onAction(action: WalletScreenAction) { - when (action) { - WalletScreenAction.SwitchUnit -> switchUnit() - WalletScreenAction.UpdateBalance -> updateBalance() - WalletScreenAction.ActivateCbfNode -> activateKyoto() - WalletScreenAction.StopKyotoNode -> stopKyotoNode() - WalletScreenAction.ClearSnackbar -> clearSnackbar() - } - } - - private fun showSnackbar(message: String) { - state = state.copy(snackbarMessage = message) - } - - private fun clearSnackbar() { - state = state.copy(snackbarMessage = null) - } - - private fun switchUnit() { - state = - when (state.unit) { - CurrencyUnit.Bitcoin -> state.copy(unit = CurrencyUnit.Satoshi) - CurrencyUnit.Satoshi -> state.copy(unit = CurrencyUnit.Bitcoin) - } - } - - private fun updateLatestBlock(blockHeight: UInt) { - state = state.copy(bestBlockHeight = blockHeight) - } - - private fun updateBalance() { - viewModelScope.launch(Dispatchers.IO) { - val newBalance = wallet.getBalance() - Log.i("Kyoto", "New balance: $newBalance") - DwLogger.log(INFO, "New balance: $newBalance") - - state = state.copy(balance = newBalance) - Log.i("Kyoto", "New state object: $state") - DwLogger.log(INFO, "New state object: $state") - } - } - - private fun activateKyoto() { - val dataDir = wallet.internalAppFilesPath - this.kyoto = Kyoto.create(wallet.wallet, dataDir, wallet.network) - val updatesFlow = kyoto!!.start() - kyotoCoroutineScope.launch { - updatesFlow.collect { - Log.i(TAG, "Collecting a flow update") - wallet.applyUpdate(it) - updateBalance() - updateBestBlock() - } - } - kyoto!!.logToLogcat() - } - - private fun stopKyotoNode() { - kyoto!!.shutdown() - } - - private fun updateBestBlock() { - val bestBlockHeight = wallet.bestBlock() - state = state.copy(bestBlockHeight = bestBlockHeight) - } -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/mvi/MviReceiveScreen.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/mvi/MviReceiveScreen.kt deleted file mode 100644 index c1fa731..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/mvi/MviReceiveScreen.kt +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.viewmodels.mvi - -data class ReceiveScreenState( - val address: String? = null, - val addressIndex: UInt? = null, -) - -sealed interface ReceiveScreenAction { - data object UpdateAddress : ReceiveScreenAction -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/mvi/MviSendScreen.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/mvi/MviSendScreen.kt deleted file mode 100644 index eee1809..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/mvi/MviSendScreen.kt +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.viewmodels.mvi - -// data class SendScreenState( -// val address: String? = null, -// ) - -sealed class SendScreenAction { - data class Broadcast(val txDataBundle: TxDataBundle) : SendScreenAction() -} - -data class TxDataBundle( - val recipients: List, - val feeRate: ULong, - val transactionType: TransactionType, - val rbfDisabled: Boolean = false, - val opReturnMsg: String? = null, -) - -data class Recipient(var address: String, var amount: ULong) - -enum class TransactionType { - STANDARD, - SEND_ALL, -} diff --git a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/mvi/MviWalletScreen.kt b/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/mvi/MviWalletScreen.kt deleted file mode 100644 index d2726a6..0000000 --- a/newbuildsystem/src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/mvi/MviWalletScreen.kt +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.presentation.viewmodels.mvi - -import org.bitcoindevkit.devkitwallet.domain.CurrencyUnit - -data class WalletScreenState( - val balance: ULong = 0u, - val unit: CurrencyUnit = CurrencyUnit.Bitcoin, - val bestBlockHeight: UInt = 0u, - val snackbarMessage: String? = null, - val kyotoNodeStatus: CbfNodeStatus = CbfNodeStatus.Stopped, -) - -sealed interface WalletScreenAction { - data object UpdateBalance : WalletScreenAction - - data object SwitchUnit : WalletScreenAction - - data object ActivateCbfNode : WalletScreenAction - - data object StopKyotoNode : WalletScreenAction - - data object ClearSnackbar : WalletScreenAction -} - -enum class CbfNodeStatus { - Running, - Stopped, -} diff --git a/app/src/main/res/drawable/bdk_logo.xml b/res/drawable/bdk_logo.xml similarity index 100% rename from app/src/main/res/drawable/bdk_logo.xml rename to res/drawable/bdk_logo.xml diff --git a/app/src/main/res/drawable/bdk_logo2.xml b/res/drawable/bdk_logo2.xml similarity index 100% rename from app/src/main/res/drawable/bdk_logo2.xml rename to res/drawable/bdk_logo2.xml diff --git a/app/src/main/res/drawable/ic_launcher_bdk_background.xml b/res/drawable/ic_launcher_bdk_background.xml similarity index 100% rename from app/src/main/res/drawable/ic_launcher_bdk_background.xml rename to res/drawable/ic_launcher_bdk_background.xml diff --git a/app/src/main/res/drawable/ic_launcher_bdk_foreground.xml b/res/drawable/ic_launcher_bdk_foreground.xml similarity index 100% rename from app/src/main/res/drawable/ic_launcher_bdk_foreground.xml rename to res/drawable/ic_launcher_bdk_foreground.xml diff --git a/app/src/main/res/drawable/ic_launcher_bdk_foreground_no_outline.xml b/res/drawable/ic_launcher_bdk_foreground_no_outline.xml similarity index 100% rename from app/src/main/res/drawable/ic_launcher_bdk_foreground_no_outline.xml rename to res/drawable/ic_launcher_bdk_foreground_no_outline.xml diff --git a/app/src/main/res/font/google_sans_code_light.ttf b/res/font/google_sans_code_light.ttf similarity index 100% rename from app/src/main/res/font/google_sans_code_light.ttf rename to res/font/google_sans_code_light.ttf diff --git a/app/src/main/res/font/inter_bold.ttf b/res/font/inter_bold.ttf similarity index 100% rename from app/src/main/res/font/inter_bold.ttf rename to res/font/inter_bold.ttf diff --git a/app/src/main/res/font/inter_medium.ttf b/res/font/inter_medium.ttf similarity index 100% rename from app/src/main/res/font/inter_medium.ttf rename to res/font/inter_medium.ttf diff --git a/app/src/main/res/font/inter_regular.ttf b/res/font/inter_regular.ttf similarity index 100% rename from app/src/main/res/font/inter_regular.ttf rename to res/font/inter_regular.ttf diff --git a/app/src/main/res/font/inter_thin.ttf b/res/font/inter_thin.ttf similarity index 100% rename from app/src/main/res/font/inter_thin.ttf rename to res/font/inter_thin.ttf diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/res/mipmap-anydpi-v26/ic_launcher.xml similarity index 100% rename from app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml rename to res/mipmap-anydpi-v26/ic_launcher.xml diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_bdk.xml b/res/mipmap-anydpi-v26/ic_launcher_bdk.xml similarity index 100% rename from app/src/main/res/mipmap-anydpi-v26/ic_launcher_bdk.xml rename to res/mipmap-anydpi-v26/ic_launcher_bdk.xml diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_bdk_round.xml b/res/mipmap-anydpi-v26/ic_launcher_bdk_round.xml similarity index 100% rename from app/src/main/res/mipmap-anydpi-v26/ic_launcher_bdk_round.xml rename to res/mipmap-anydpi-v26/ic_launcher_bdk_round.xml diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/res/mipmap-hdpi/ic_launcher.png similarity index 100% rename from app/src/main/res/mipmap-hdpi/ic_launcher.png rename to res/mipmap-hdpi/ic_launcher.png diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_bdk.png b/res/mipmap-hdpi/ic_launcher_bdk.png similarity index 100% rename from app/src/main/res/mipmap-hdpi/ic_launcher_bdk.png rename to res/mipmap-hdpi/ic_launcher_bdk.png diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_bdk_round.png b/res/mipmap-hdpi/ic_launcher_bdk_round.png similarity index 100% rename from app/src/main/res/mipmap-hdpi/ic_launcher_bdk_round.png rename to res/mipmap-hdpi/ic_launcher_bdk_round.png diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/res/mipmap-hdpi/ic_launcher_round.png similarity index 100% rename from app/src/main/res/mipmap-hdpi/ic_launcher_round.png rename to res/mipmap-hdpi/ic_launcher_round.png diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/res/mipmap-mdpi/ic_launcher.png similarity index 100% rename from app/src/main/res/mipmap-mdpi/ic_launcher.png rename to res/mipmap-mdpi/ic_launcher.png diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_bdk.png b/res/mipmap-mdpi/ic_launcher_bdk.png similarity index 100% rename from app/src/main/res/mipmap-mdpi/ic_launcher_bdk.png rename to res/mipmap-mdpi/ic_launcher_bdk.png diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_bdk_round.png b/res/mipmap-mdpi/ic_launcher_bdk_round.png similarity index 100% rename from app/src/main/res/mipmap-mdpi/ic_launcher_bdk_round.png rename to res/mipmap-mdpi/ic_launcher_bdk_round.png diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/res/mipmap-mdpi/ic_launcher_round.png similarity index 100% rename from app/src/main/res/mipmap-mdpi/ic_launcher_round.png rename to res/mipmap-mdpi/ic_launcher_round.png diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/res/mipmap-xhdpi/ic_launcher.png similarity index 100% rename from app/src/main/res/mipmap-xhdpi/ic_launcher.png rename to res/mipmap-xhdpi/ic_launcher.png diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_bdk.png b/res/mipmap-xhdpi/ic_launcher_bdk.png similarity index 100% rename from app/src/main/res/mipmap-xhdpi/ic_launcher_bdk.png rename to res/mipmap-xhdpi/ic_launcher_bdk.png diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_bdk_round.png b/res/mipmap-xhdpi/ic_launcher_bdk_round.png similarity index 100% rename from app/src/main/res/mipmap-xhdpi/ic_launcher_bdk_round.png rename to res/mipmap-xhdpi/ic_launcher_bdk_round.png diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/res/mipmap-xhdpi/ic_launcher_round.png similarity index 100% rename from app/src/main/res/mipmap-xhdpi/ic_launcher_round.png rename to res/mipmap-xhdpi/ic_launcher_round.png diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/res/mipmap-xxhdpi/ic_launcher.png similarity index 100% rename from app/src/main/res/mipmap-xxhdpi/ic_launcher.png rename to res/mipmap-xxhdpi/ic_launcher.png diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_bdk.png b/res/mipmap-xxhdpi/ic_launcher_bdk.png similarity index 100% rename from app/src/main/res/mipmap-xxhdpi/ic_launcher_bdk.png rename to res/mipmap-xxhdpi/ic_launcher_bdk.png diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_bdk_round.png b/res/mipmap-xxhdpi/ic_launcher_bdk_round.png similarity index 100% rename from app/src/main/res/mipmap-xxhdpi/ic_launcher_bdk_round.png rename to res/mipmap-xxhdpi/ic_launcher_bdk_round.png diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/res/mipmap-xxhdpi/ic_launcher_round.png similarity index 100% rename from app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png rename to res/mipmap-xxhdpi/ic_launcher_round.png diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/res/mipmap-xxxhdpi/ic_launcher.png similarity index 100% rename from app/src/main/res/mipmap-xxxhdpi/ic_launcher.png rename to res/mipmap-xxxhdpi/ic_launcher.png diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_bdk.png b/res/mipmap-xxxhdpi/ic_launcher_bdk.png similarity index 100% rename from app/src/main/res/mipmap-xxxhdpi/ic_launcher_bdk.png rename to res/mipmap-xxxhdpi/ic_launcher_bdk.png diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_bdk_round.png b/res/mipmap-xxxhdpi/ic_launcher_bdk_round.png similarity index 100% rename from app/src/main/res/mipmap-xxxhdpi/ic_launcher_bdk_round.png rename to res/mipmap-xxxhdpi/ic_launcher_bdk_round.png diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/res/mipmap-xxxhdpi/ic_launcher_round.png similarity index 100% rename from app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png rename to res/mipmap-xxxhdpi/ic_launcher_round.png diff --git a/app/src/main/res/values/colors.xml b/res/values/colors.xml similarity index 100% rename from app/src/main/res/values/colors.xml rename to res/values/colors.xml diff --git a/app/src/main/res/values/splash.xml b/res/values/splash.xml similarity index 100% rename from app/src/main/res/values/splash.xml rename to res/values/splash.xml diff --git a/app/src/main/res/values/strings.xml b/res/values/strings.xml similarity index 100% rename from app/src/main/res/values/strings.xml rename to res/values/strings.xml diff --git a/app/src/main/res/values/themes.xml b/res/values/themes.xml similarity index 100% rename from app/src/main/res/values/themes.xml rename to res/values/themes.xml diff --git a/settings.gradle.kts b/settings.gradle.kts deleted file mode 100644 index 98bc263..0000000 --- a/settings.gradle.kts +++ /dev/null @@ -1,23 +0,0 @@ -rootProject.name = "Devkit Wallet" -include("app") - -pluginManagement { - repositories { - google() - gradlePluginPortal() - mavenCentral() - } -} - -dependencyResolutionManagement { - repositories { - google() - mavenCentral() - - // Snapshots repository - maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") - - // Local Maven (~/.m2/repository/) - mavenLocal() - } -} diff --git a/app/src/main/AndroidManifest.xml b/src/AndroidManifest.xml similarity index 100% rename from app/src/main/AndroidManifest.xml rename to src/AndroidManifest.xml diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/data/Kyoto.kt b/src/org/bitcoindevkit/devkitwallet/data/Kyoto.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/data/Kyoto.kt rename to src/org/bitcoindevkit/devkitwallet/data/Kyoto.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/data/TxDetails.kt b/src/org/bitcoindevkit/devkitwallet/data/TxDetails.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/data/TxDetails.kt rename to src/org/bitcoindevkit/devkitwallet/data/TxDetails.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/data/WalletConfigs.kt b/src/org/bitcoindevkit/devkitwallet/data/WalletConfigs.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/data/WalletConfigs.kt rename to src/org/bitcoindevkit/devkitwallet/data/WalletConfigs.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/data/datastore/AppSettings.kt b/src/org/bitcoindevkit/devkitwallet/data/datastore/AppSettings.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/data/datastore/AppSettings.kt rename to src/org/bitcoindevkit/devkitwallet/data/datastore/AppSettings.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/data/datastore/WalletData.kt b/src/org/bitcoindevkit/devkitwallet/data/datastore/WalletData.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/data/datastore/WalletData.kt rename to src/org/bitcoindevkit/devkitwallet/data/datastore/WalletData.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/domain/AppSettingsRepository.kt b/src/org/bitcoindevkit/devkitwallet/domain/AppSettingsRepository.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/domain/AppSettingsRepository.kt rename to src/org/bitcoindevkit/devkitwallet/domain/AppSettingsRepository.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/domain/Constants.kt b/src/org/bitcoindevkit/devkitwallet/domain/Constants.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/domain/Constants.kt rename to src/org/bitcoindevkit/devkitwallet/domain/Constants.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/domain/CurrencyUnit.kt b/src/org/bitcoindevkit/devkitwallet/domain/CurrencyUnit.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/domain/CurrencyUnit.kt rename to src/org/bitcoindevkit/devkitwallet/domain/CurrencyUnit.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/domain/DwLogger.kt b/src/org/bitcoindevkit/devkitwallet/domain/DwLogger.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/domain/DwLogger.kt rename to src/org/bitcoindevkit/devkitwallet/domain/DwLogger.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/domain/Wallet.kt b/src/org/bitcoindevkit/devkitwallet/domain/Wallet.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/domain/Wallet.kt rename to src/org/bitcoindevkit/devkitwallet/domain/Wallet.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/domain/WalletRepository.kt b/src/org/bitcoindevkit/devkitwallet/domain/WalletRepository.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/domain/WalletRepository.kt rename to src/org/bitcoindevkit/devkitwallet/domain/WalletRepository.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/domain/utils/FormatInBtc.kt b/src/org/bitcoindevkit/devkitwallet/domain/utils/FormatInBtc.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/domain/utils/FormatInBtc.kt rename to src/org/bitcoindevkit/devkitwallet/domain/utils/FormatInBtc.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/domain/utils/ProtobufExtensions.kt b/src/org/bitcoindevkit/devkitwallet/domain/utils/ProtobufExtensions.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/domain/utils/ProtobufExtensions.kt rename to src/org/bitcoindevkit/devkitwallet/domain/utils/ProtobufExtensions.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/domain/utils/Timestamps.kt b/src/org/bitcoindevkit/devkitwallet/domain/utils/Timestamps.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/domain/utils/Timestamps.kt rename to src/org/bitcoindevkit/devkitwallet/domain/utils/Timestamps.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/DevkitWalletActivity.kt b/src/org/bitcoindevkit/devkitwallet/presentation/DevkitWalletActivity.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/DevkitWalletActivity.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/DevkitWalletActivity.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/navigation/AppNavigation.kt b/src/org/bitcoindevkit/devkitwallet/presentation/navigation/AppNavigation.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/navigation/AppNavigation.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/navigation/AppNavigation.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/navigation/Destinations.kt b/src/org/bitcoindevkit/devkitwallet/presentation/navigation/Destinations.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/navigation/Destinations.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/navigation/Destinations.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/theme/DevkitWalletColors.kt b/src/org/bitcoindevkit/devkitwallet/presentation/theme/DevkitWalletColors.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/theme/DevkitWalletColors.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/theme/DevkitWalletColors.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/theme/Fonts.kt b/src/org/bitcoindevkit/devkitwallet/presentation/theme/Fonts.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/theme/Fonts.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/theme/Fonts.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/theme/Theme.kt b/src/org/bitcoindevkit/devkitwallet/presentation/theme/Theme.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/theme/Theme.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/theme/Theme.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/theme/Type.kt b/src/org/bitcoindevkit/devkitwallet/presentation/theme/Type.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/theme/Type.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/theme/Type.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/components/CustomSnackbar.kt b/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/CustomSnackbar.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/components/CustomSnackbar.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/ui/components/CustomSnackbar.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/components/LoadingAnimation.kt b/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/LoadingAnimation.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/components/LoadingAnimation.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/ui/components/LoadingAnimation.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/components/NeutralButton.kt b/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/NeutralButton.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/components/NeutralButton.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/ui/components/NeutralButton.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/components/RadioButtonWithLabel.kt b/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/RadioButtonWithLabel.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/components/RadioButtonWithLabel.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/ui/components/RadioButtonWithLabel.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/components/SecondaryScreensAppBar.kt b/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/SecondaryScreensAppBar.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/components/SecondaryScreensAppBar.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/ui/components/SecondaryScreensAppBar.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/components/TransactionCards.kt b/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/TransactionCards.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/components/TransactionCards.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/ui/components/TransactionCards.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/components/WalletOptionsCard.kt b/src/org/bitcoindevkit/devkitwallet/presentation/ui/components/WalletOptionsCard.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/components/WalletOptionsCard.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/ui/components/WalletOptionsCard.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/ActiveWalletsScreen.kt b/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/ActiveWalletsScreen.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/ActiveWalletsScreen.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/ActiveWalletsScreen.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/CreateNewWallet.kt b/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/CreateNewWallet.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/CreateNewWallet.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/CreateNewWallet.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/OnboardingScreen.kt b/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/OnboardingScreen.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/OnboardingScreen.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/OnboardingScreen.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/RecoverWalletScreen.kt b/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/RecoverWalletScreen.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/RecoverWalletScreen.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/RecoverWalletScreen.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/WalletChoiceScreen.kt b/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/WalletChoiceScreen.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/WalletChoiceScreen.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/WalletChoiceScreen.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/AboutScreen.kt b/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/AboutScreen.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/AboutScreen.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/AboutScreen.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/BlockchainClientScreen.kt b/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/BlockchainClientScreen.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/BlockchainClientScreen.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/BlockchainClientScreen.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/CustomBlockchainClient.kt b/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/CustomBlockchainClient.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/CustomBlockchainClient.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/CustomBlockchainClient.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/LogsScreen.kt b/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/LogsScreen.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/LogsScreen.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/LogsScreen.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/RecoveryDataScreen.kt b/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/RecoveryDataScreen.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/RecoveryDataScreen.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/RecoveryDataScreen.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/SettingsScreen.kt b/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/SettingsScreen.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/SettingsScreen.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/SettingsScreen.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/ThemeScreen.kt b/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/ThemeScreen.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/ThemeScreen.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/settings/ThemeScreen.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/RBFScreen.kt b/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/RBFScreen.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/RBFScreen.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/RBFScreen.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/ReceiveScreen.kt b/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/ReceiveScreen.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/ReceiveScreen.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/ReceiveScreen.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/SendScreen.kt b/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/SendScreen.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/SendScreen.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/SendScreen.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/TransactionHistoryScreen.kt b/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/TransactionHistoryScreen.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/TransactionHistoryScreen.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/TransactionHistoryScreen.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/TransactionScreen.kt b/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/TransactionScreen.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/TransactionScreen.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/TransactionScreen.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/WalletHomeScreen.kt b/src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/WalletHomeScreen.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/WalletHomeScreen.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/ui/screens/wallet/WalletHomeScreen.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/viewmodels/AddressViewModel.kt b/src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/AddressViewModel.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/viewmodels/AddressViewModel.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/AddressViewModel.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/viewmodels/SendViewModel.kt b/src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/SendViewModel.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/viewmodels/SendViewModel.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/SendViewModel.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/viewmodels/WalletViewModel.kt b/src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/WalletViewModel.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/viewmodels/WalletViewModel.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/WalletViewModel.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/viewmodels/mvi/MviReceiveScreen.kt b/src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/mvi/MviReceiveScreen.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/viewmodels/mvi/MviReceiveScreen.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/mvi/MviReceiveScreen.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/viewmodels/mvi/MviSendScreen.kt b/src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/mvi/MviSendScreen.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/viewmodels/mvi/MviSendScreen.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/mvi/MviSendScreen.kt diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/viewmodels/mvi/MviWalletScreen.kt b/src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/mvi/MviWalletScreen.kt similarity index 100% rename from app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/viewmodels/mvi/MviWalletScreen.kt rename to src/org/bitcoindevkit/devkitwallet/presentation/viewmodels/mvi/MviWalletScreen.kt