Skip to content

Commit

Permalink
Merge pull request #73 from tonkeeper/keystone
Browse files Browse the repository at this point in the history
Keystone
  • Loading branch information
polstianka authored Sep 19, 2024
2 parents 14b52f4 + 59f34c4 commit a6262de
Show file tree
Hide file tree
Showing 118 changed files with 6,590 additions and 598 deletions.
10 changes: 10 additions & 0 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/kotlinc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apps/wallet/data/account/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
plugins {
id("com.tonapps.wallet.data")
id("kotlin-parcelize")
kotlin("plugin.serialization") version "2.0.0"
kotlin("plugin.serialization")
}

android {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import com.tonapps.wallet.data.account.source.DatabaseSource
import com.tonapps.wallet.data.account.source.StorageSource
import com.tonapps.wallet.data.account.source.VaultSource
import com.tonapps.wallet.data.rn.RNLegacy
import com.tonapps.wallet.data.rn.data.RNKeystone
import com.tonapps.wallet.data.rn.data.RNLedger
import com.tonapps.wallet.data.rn.data.RNWallet
import kotlinx.coroutines.CoroutineScope
Expand Down Expand Up @@ -87,18 +88,6 @@ class AccountRepository(
val selectedId: String?
get() = (selectedStateFlow.value as? SelectedState.Wallet)?.wallet?.id

@OptIn(ExperimentalCoroutinesApi::class)
val realtimeEventsFlow = selectedWalletFlow.flatMapLatest { wallet ->
api.accountEvents(wallet.accountId, wallet.testnet).map { event ->
val isBoc = event.json.has("boc")
if (isBoc) {
WalletEvent.Boc(wallet, event.json)
} else {
WalletEvent.Transaction(wallet, event.json)
}
}
}.flowOn(Dispatchers.IO).shareIn(scope, SharingStarted.Eagerly, 1)

init {
scope.launch(Dispatchers.IO) {
if (rnLegacy.isRequestMainMigration()) {
Expand Down Expand Up @@ -145,6 +134,7 @@ class AccountRepository(
Wallet.Type.SignerQR -> RNWallet.Type.Signer
Wallet.Type.Signer -> RNWallet.Type.SignerDeeplink
Wallet.Type.Ledger -> RNWallet.Type.Ledger
Wallet.Type.Keystone -> RNWallet.Type.Keystone
else -> RNWallet.Type.Regular
}

Expand All @@ -166,6 +156,12 @@ class AccountRepository(
accountIndex = it.accountIndex
)
},
keystone = wallet.keystone?.let {
RNKeystone(
xfp = it.xfp,
path = it.path
)
}
)

rnLegacy.addWallet(rnWallet)
Expand Down Expand Up @@ -265,6 +261,25 @@ class AccountRepository(
return addWallet(versions.map { newWalletId() }, label, publicKey, versions, type)
}

suspend fun pairKeystone(
label: Wallet.Label,
publicKey: PublicKeyEd25519,
keystone: WalletEntity.Keystone,
): List<WalletEntity> {
val entity = WalletEntity(
id = newWalletId(),
publicKey = publicKey,
type = Wallet.Type.Keystone,
version = WalletVersion.V4R2,
label = label,
keystone = keystone
)

val list = listOf(entity)
insertWallets(list)
return list
}

suspend fun importWallet(
ids: List<String>,
label: Wallet.Label,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ internal class RNMigrationHelper(
type = Wallet.Type.SignerQR
} else if (legacyWallet.type == RNWallet.Type.Ledger) {
type = Wallet.Type.Ledger
} else if (legacyWallet.type == RNWallet.Type.Keystone) {
type = Wallet.Type.Keystone
} else {
continue
}
Expand All @@ -75,6 +77,12 @@ internal class RNMigrationHelper(
deviceId = it.deviceId,
accountIndex = it.accountIndex
)
},
keystone = legacyWallet.keystone?.let {
WalletEntity.Keystone(
xfp = it.xfp,
path = it.path
)
}
)
list.add(entity)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ sealed class Wallet {
}

enum class Type(val id: Int) {
Default(0), Watch(1), Testnet(2), Signer(3), Lockup(4), Ledger(5), SignerQR(6)
Default(0), Watch(1), Testnet(2), Signer(3), Lockup(4), Ledger(5), SignerQR(6), Keystone(7)
}

@Parcelize
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ import org.ton.api.pub.PublicKeyEd25519
import org.ton.cell.Cell
import org.ton.contract.wallet.WalletTransfer


data class WalletEntity(
val id: String,
val publicKey: PublicKeyEd25519,
val type: Wallet.Type,
val version: WalletVersion,
val label: Wallet.Label,
val ledger: Ledger? = null,
val keystone: Keystone? = null
): Parcelable {

companion object {
Expand All @@ -41,7 +41,8 @@ data class WalletEntity(
type = Wallet.Type.Default,
version = WalletVersion.V5BETA,
label = Wallet.Label("", "", 0),
ledger = null
ledger = null,
keystone = null
)

@JvmField
Expand All @@ -58,6 +59,12 @@ data class WalletEntity(
val accountIndex: Int
) : Parcelable

@Parcelize
data class Keystone(
val xfp: String,
val path: String
) : Parcelable

val contract: BaseWalletContract by lazy {
val network = if (testnet) TonNetwork.TESTNET.value else TonNetwork.MAINNET.value

Expand All @@ -83,19 +90,23 @@ data class WalletEntity(
val isLedger: Boolean
get() = type == Wallet.Type.Ledger

val isKeystone: Boolean
get() = type == Wallet.Type.Keystone

val isW5: Boolean
get() = version == WalletVersion.V5BETA || version == WalletVersion.V5R1

val isExternal: Boolean
get() = signer || isLedger
get() = signer || isLedger || isKeystone

constructor(parcel: Parcel) : this(
id = parcel.readString()!!,
publicKey = parcel.readString()!!.publicKey(),
type = parcel.readEnum(Wallet.Type::class.java)!!,
version = parcel.readEnum(WalletVersion::class.java)!!,
label = parcel.readParcelableCompat()!!,
ledger = parcel.readParcelableCompat()
ledger = parcel.readParcelableCompat(),
keystone = parcel.readParcelableCompat()
)

fun isMyAddress(address: String): Boolean {
Expand Down Expand Up @@ -140,6 +151,7 @@ data class WalletEntity(
parcel.writeEnum(version)
parcel.writeParcelable(label, flags)
parcel.writeParcelable(ledger, flags)
parcel.writeParcelable(keystone, flags)
}

override fun describeContents(): Int {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ internal class DatabaseSource(

private companion object {
private const val DATABASE_NAME = "account"
private const val DATABASE_VERSION = 2
private const val DATABASE_VERSION = 3

private const val WALLET_TABLE_NAME = "wallet"
private const val WALLET_TABLE_ID_COLUMN = "id"
Expand All @@ -33,6 +33,9 @@ internal class DatabaseSource(
private const val WALLET_TABLE_LEDGER_DEVICE_ID = "ledger_device_id"
private const val WALLET_TABLE_LEDGER_ACCOUNT_INDEX = "ledger_account_index"

private const val WALLET_TABLE_KEYSTONE_XFP = "keystone_xfp"
private const val WALLET_TABLE_KEYSTONE_PATH = "keystone_path"

private fun WalletEntity.toValues(): ContentValues {
val values = ContentValues()
values.put(WALLET_TABLE_ID_COLUMN, id)
Expand All @@ -44,6 +47,10 @@ internal class DatabaseSource(
values.put(WALLET_TABLE_LEDGER_DEVICE_ID, it.deviceId)
values.put(WALLET_TABLE_LEDGER_ACCOUNT_INDEX, it.accountIndex)
}
keystone?.let {
values.put(WALLET_TABLE_KEYSTONE_XFP, it.xfp)
values.put(WALLET_TABLE_KEYSTONE_PATH, it.path)
}
return values
}
}
Expand All @@ -56,7 +63,9 @@ internal class DatabaseSource(
"$WALLET_TABLE_VERSION TEXT," +
"$WALLET_TABLE_LABEL BLOB," +
"$WALLET_TABLE_LEDGER_DEVICE_ID TEXT," +
"$WALLET_TABLE_LEDGER_ACCOUNT_INDEX INTEGER" +
"$WALLET_TABLE_LEDGER_ACCOUNT_INDEX INTEGER," +
"$WALLET_TABLE_KEYSTONE_XFP TEXT," +
"$WALLET_TABLE_KEYSTONE_PATH TEXT" +
");")

val walletIndexPrefix = "idx_$WALLET_TABLE_NAME"
Expand All @@ -66,10 +75,15 @@ internal class DatabaseSource(
}

override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
if (oldVersion == 1 && newVersion == 2) {
if (1 >= oldVersion && newVersion == 2) {
db.execSQL("ALTER TABLE $WALLET_TABLE_NAME ADD COLUMN $WALLET_TABLE_LEDGER_DEVICE_ID TEXT;")
db.execSQL("ALTER TABLE $WALLET_TABLE_NAME ADD COLUMN $WALLET_TABLE_LEDGER_ACCOUNT_INDEX INTEGER;")
}

if (2 >= oldVersion && newVersion == 3) {
db.execSQL("ALTER TABLE $WALLET_TABLE_NAME ADD COLUMN $WALLET_TABLE_KEYSTONE_XFP TEXT;")
db.execSQL("ALTER TABLE $WALLET_TABLE_NAME ADD COLUMN $WALLET_TABLE_KEYSTONE_PATH TEXT;")
}
}

suspend fun clearAccounts() = withContext(scope.coroutineContext) {
Expand Down Expand Up @@ -101,14 +115,14 @@ internal class DatabaseSource(
}

suspend fun getAccounts(): List<WalletEntity> = withContext(scope.coroutineContext) {
val query = "SELECT $WALLET_TABLE_ID_COLUMN, $WALLET_TABLE_ID_PUBLIC_KEY, $WALLET_TABLE_TYPE, $WALLET_TABLE_VERSION, $WALLET_TABLE_LABEL, $WALLET_TABLE_LEDGER_DEVICE_ID, $WALLET_TABLE_LEDGER_ACCOUNT_INDEX FROM $WALLET_TABLE_NAME LIMIT 1000;"
val query = "SELECT $WALLET_TABLE_ID_COLUMN, $WALLET_TABLE_ID_PUBLIC_KEY, $WALLET_TABLE_TYPE, $WALLET_TABLE_VERSION, $WALLET_TABLE_LABEL, $WALLET_TABLE_LEDGER_DEVICE_ID, $WALLET_TABLE_LEDGER_ACCOUNT_INDEX, $WALLET_TABLE_KEYSTONE_XFP, $WALLET_TABLE_KEYSTONE_PATH FROM $WALLET_TABLE_NAME LIMIT 1000;"
val cursor = readableDatabase.rawQuery(query, null)
readAccounts(cursor)
}

suspend fun getAccount(id: String): WalletEntity? = withContext(scope.coroutineContext) {
if (id.isNotBlank()) {
val query = "SELECT $WALLET_TABLE_ID_COLUMN, $WALLET_TABLE_ID_PUBLIC_KEY, $WALLET_TABLE_TYPE, $WALLET_TABLE_VERSION, $WALLET_TABLE_LABEL, $WALLET_TABLE_LEDGER_DEVICE_ID, $WALLET_TABLE_LEDGER_ACCOUNT_INDEX FROM $WALLET_TABLE_NAME WHERE $WALLET_TABLE_ID_COLUMN = ?;"
val query = "SELECT $WALLET_TABLE_ID_COLUMN, $WALLET_TABLE_ID_PUBLIC_KEY, $WALLET_TABLE_TYPE, $WALLET_TABLE_VERSION, $WALLET_TABLE_LABEL, $WALLET_TABLE_LEDGER_DEVICE_ID, $WALLET_TABLE_LEDGER_ACCOUNT_INDEX, $WALLET_TABLE_KEYSTONE_XFP, $WALLET_TABLE_KEYSTONE_PATH FROM $WALLET_TABLE_NAME WHERE $WALLET_TABLE_ID_COLUMN = ?;"
val cursor = readableDatabase.rawQuery(query, arrayOf(id))
readAccounts(cursor).firstOrNull()
} else {
Expand Down Expand Up @@ -137,6 +151,8 @@ internal class DatabaseSource(
val labelIndex = cursor.getColumnIndex(WALLET_TABLE_LABEL)
val ledgerDeviceIdIndex = cursor.getColumnIndex(WALLET_TABLE_LEDGER_DEVICE_ID)
val ledgerAccountIndexIndex = cursor.getColumnIndex(WALLET_TABLE_LEDGER_ACCOUNT_INDEX)
val keystoneXfpIndex = cursor.getColumnIndex(WALLET_TABLE_KEYSTONE_XFP)
val keystonePathIndex = cursor.getColumnIndex(WALLET_TABLE_KEYSTONE_PATH)
val accounts = mutableListOf<WalletEntity>()
while (cursor.moveToNext()) {
val wallet = WalletEntity(
Expand All @@ -147,12 +163,23 @@ internal class DatabaseSource(
label = cursor.getBlob(labelIndex).toParcel<Wallet.Label>()!!
)
if (wallet.type == Wallet.Type.Ledger) {
accounts.add(wallet.copy(
ledger = WalletEntity.Ledger(
deviceId = cursor.getString(ledgerDeviceIdIndex),
accountIndex = cursor.getInt(ledgerAccountIndexIndex)
accounts.add(
wallet.copy(
ledger = WalletEntity.Ledger(
deviceId = cursor.getString(ledgerDeviceIdIndex),
accountIndex = cursor.getInt(ledgerAccountIndexIndex)
)
)
)
} else if (wallet.type == Wallet.Type.Keystone) {
accounts.add(
wallet.copy(
keystone = WalletEntity.Keystone(
xfp = cursor.getString(keystoneXfpIndex),
path = cursor.getString(keystonePathIndex)
)
)
))
)
} else {
accounts.add(wallet)
}
Expand Down
2 changes: 1 addition & 1 deletion apps/wallet/data/purchase/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
plugins {
id("com.tonapps.wallet.data")
id("kotlin-parcelize")
kotlin("plugin.serialization") version "2.0.0"
kotlin("plugin.serialization")
}

android {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.tonapps.wallet.data.rn.data

import org.json.JSONObject

data class RNKeystone(
val xfp: String,
val path: String
): RNData() {

constructor(json: JSONObject) : this(
json.getString("xfp"),
json.getString("path")
)

override fun toJSON(): JSONObject {
return JSONObject().apply {
put("xfp", xfp)
put("path", path)
}
}
}
Loading

0 comments on commit a6262de

Please sign in to comment.