Skip to content

Commit 1d16c65

Browse files
committed
fat(flipcash): update account service to allow get account with filtering
Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
1 parent 5ce0769 commit 1d16c65

11 files changed

Lines changed: 79 additions & 34 deletions

File tree

apps/flipcash/shared/payments/src/main/kotlin/com/flipcash/app/payments/internal/InternalPoolResolveDelegate.kt

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import com.getcode.opencode.controllers.AccountController
1616
import com.getcode.opencode.controllers.TransactionController
1717
import com.getcode.opencode.exchange.Exchange
1818
import com.getcode.opencode.model.accounts.AccountCluster
19+
import com.getcode.opencode.model.accounts.AccountFilter
1920
import com.getcode.opencode.model.accounts.AccountType
2021
import com.getcode.opencode.model.core.ID
2122
import com.getcode.opencode.model.core.RandomId
@@ -97,12 +98,7 @@ class InternalPoolResolveDelegate @Inject constructor(
9798
val poolBalance = accountController.getAccount(
9899
accountOwner = owner,
99100
requestingOwner = owner,
100-
predicate = { account ->
101-
val indexMatch = account.index.toLong() == pool.derivationIndex
102-
val addressMatch = account.address == pool.fundingDestination
103-
val isPool = account.accountType == AccountType.Pool
104-
indexMatch && addressMatch && isPool
105-
},
101+
filter = AccountFilter.TokenAddress(pool.fundingDestination),
106102
).getOrNull()?.balance
107103

108104
if (poolBalance == null) {

apps/flipcash/shared/pools/src/main/kotlin/com/flipcash/app/pools/PoolsCoordinator.kt

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import com.flipcash.services.models.QueryOptions
2424
import com.flipcash.services.user.UserManager
2525
import com.getcode.ed25519.Ed25519.KeyPair
2626
import com.getcode.opencode.controllers.AccountController
27+
import com.getcode.opencode.model.accounts.AccountFilter
2728
import com.getcode.opencode.model.accounts.AccountInfo
2829
import com.getcode.opencode.model.accounts.AccountType
2930
import com.getcode.opencode.model.core.ID
@@ -137,12 +138,7 @@ class PoolsCoordinator @Inject constructor(
137138
return accountController.getAccount(
138139
accountOwner = owner,
139140
requestingOwner = owner,
140-
predicate = { account ->
141-
val indexMatch = account.index.toLong() == pool.derivationIndex
142-
val addressMatch = account.address == pool.fundingDestination
143-
val isPool = account.accountType == AccountType.Pool
144-
indexMatch && addressMatch && isPool
145-
}
141+
filter = AccountFilter.TokenAddress(pool.fundingDestination)
146142
).map {
147143
it.balance == Fiat.Zero
148144
}.onFailure {
@@ -177,13 +173,20 @@ class PoolsCoordinator @Inject constructor(
177173
resolution: PoolResolution.DecisionMade,
178174
rendezvous: KeyPair
179175
): Result<Unit> {
180-
return controller.resolvePool(
181-
pool = domainToNetworkMapper.map(pool),
182-
rendezvous = rendezvous,
183-
resolution = PoolResolutionConverter.toPoolResolution(resolution as PoolResolution),
184-
).onSuccess {
185-
dataSource.resolvePool(pool.id, resolution)
186-
}
176+
// ensure we are working with an up-to-date instance of a pool
177+
return controller.getPool(pool.id)
178+
.fold(
179+
onSuccess = {
180+
controller.resolvePool(
181+
pool = domainToNetworkMapper.map(pool),
182+
rendezvous = rendezvous,
183+
resolution = PoolResolutionConverter.toPoolResolution(resolution as PoolResolution),
184+
)
185+
},
186+
onFailure = { Result.failure(it) }
187+
).onSuccess {
188+
dataSource.resolvePool(pool.id, resolution)
189+
}
187190
}
188191

189192
suspend fun placeBet(

definitions/opencode/protos/src/main/proto/account/v1/account_service.proto

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ message GetTokenAccountInfosRequest {
7171
//
7272
// This must be set when requesting_owner is present.
7373
common.v1.Signature requesting_owner_signature = 4;
74+
75+
// Filter to apply to limit response sizes
76+
oneof Filter {
77+
common.v1.SolanaAccountId filter_by_token_address = 10;
78+
common.v1.AccountType filter_by_account_type = 11;
79+
}
7480
}
7581

7682
message GetTokenAccountInfosResponse {

definitions/opencode/protos/src/main/proto/transaction/v2/transaction_service.proto

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ message ReceivePaymentsPubliclyMetadata {
347347
//
348348
// for distribution in distributions[:len(distributions)-1]
349349
// actions.push_back(NoPrivacyTransferAction(POOL, distribution.destination, distributions.quarks))
350-
// actions.push_back(NoPrivacyWithdrawAction(POOL, distributions[:len(distributions)-1].destination, distributions[:len(distributions)-1].quarks))
350+
// actions.push_back(NoPrivacyWithdrawAction(POOL, distributions[len(distributions)-1].destination, distributions[len(distributions)-1].quarks))
351351
//
352352
// Notes:
353353
// - All funds must distributed. The balance of the pool must be zero at the end of the intent

services/opencode/src/main/kotlin/com/getcode/opencode/controllers/AccountController.kt

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.getcode.crypt.MnemonicPhrase
44
import com.getcode.ed25519.Ed25519
55
import com.getcode.opencode.internal.network.api.intents.IntentCreateAccount
66
import com.getcode.opencode.model.accounts.AccountCluster
7+
import com.getcode.opencode.model.accounts.AccountFilter
78
import com.getcode.opencode.model.accounts.AccountInfo
89
import com.getcode.opencode.model.accounts.AccountResponse
910
import com.getcode.opencode.model.accounts.PoolAccount
@@ -55,19 +56,12 @@ class AccountController @Inject constructor(
5556
suspend fun getAccount(
5657
accountOwner: AccountCluster,
5758
requestingOwner: AccountCluster,
58-
predicate: (AccountInfo) -> Boolean,
59+
filter: AccountFilter,
5960
): Result<AccountInfo> {
60-
return getAccounts(
61-
accountOwner = accountOwner,
62-
requestingOwner = requestingOwner,
63-
).map {
64-
it.accounts.values.find(predicate)
65-
}.fold(
66-
onSuccess = {
67-
if (it != null) Result.success(it)
68-
else Result.failure(NoSuchElementException())
69-
},
70-
onFailure = { Result.failure(it) }
61+
return accountRepository.getAccount(
62+
accountOwner = accountOwner.authority.keyPair,
63+
requestingOwner = requestingOwner.authority.keyPair,
64+
filter = filter,
7165
)
7266
}
7367
}

services/opencode/src/main/kotlin/com/getcode/opencode/controllers/BalanceController.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ class BalanceController @Inject constructor(
137137
type = TraceType.Process
138138
)
139139

140+
// TODO: segment this to have balance utilize getAccount(filter: Primary) and timelock check and nextPoolIndex to be handled separately
140141
retryable(
141142
maxRetries = 3,
142143
call = suspend { accountController.getAccounts(owner, owner) }

services/opencode/src/main/kotlin/com/getcode/opencode/internal/domain/repositories/InternalAccountRepository.kt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package com.getcode.opencode.internal.domain.repositories
22

33
import com.getcode.ed25519.Ed25519
44
import com.getcode.opencode.internal.network.services.AccountService
5+
import com.getcode.opencode.model.accounts.AccountFilter
6+
import com.getcode.opencode.model.accounts.AccountInfo
57
import com.getcode.opencode.model.accounts.AccountResponse
68
import com.getcode.opencode.repositories.AccountRepository
79
import javax.inject.Inject
@@ -17,4 +19,21 @@ internal class InternalAccountRepository @Inject constructor(
1719
accountOwner: Ed25519.KeyPair,
1820
requestingOwner: Ed25519.KeyPair,
1921
): Result<AccountResponse> = service.getAccounts(accountOwner, requestingOwner)
22+
23+
override suspend fun getAccount(
24+
accountOwner: Ed25519.KeyPair,
25+
requestingOwner: Ed25519.KeyPair,
26+
filter: AccountFilter,
27+
): Result<AccountInfo> = service.getAccounts(accountOwner, requestingOwner, filter)
28+
.map { response -> response.accounts.values.firstOrNull() }
29+
.fold(
30+
onSuccess = {
31+
if (it != null) {
32+
Result.success(it)
33+
} else {
34+
Result.failure(Exception("Account not found"))
35+
}
36+
},
37+
onFailure = { Result.failure(it) }
38+
)
2039
}

services/opencode/src/main/kotlin/com/getcode/opencode/internal/network/api/AccountApi.kt

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import com.getcode.opencode.internal.annotations.OpenCodeManagedChannel
77
import com.getcode.opencode.internal.network.core.GrpcApi
88
import com.getcode.opencode.internal.network.extensions.asSolanaAccountId
99
import com.getcode.opencode.internal.network.extensions.sign
10+
import com.getcode.opencode.model.accounts.AccountFilter
1011
import io.grpc.ManagedChannel
1112
import kotlinx.coroutines.Dispatchers
1213
import kotlinx.coroutines.withContext
@@ -54,16 +55,29 @@ internal class AccountApi @Inject constructor(
5455
* metadata that is considered private will be provided, if applicable. An example
5556
* use case includes a user owner account requesting account info for a gift card
5657
* owner account.
57-
*
58+
* @param filter Filter to apply to limit response sizes
5859
* @return The [AccountService.GetTokenAccountInfosResponse] for the owner account.
5960
*/
6061
suspend fun getTokenAccounts(
6162
accountOwner: KeyPair,
6263
requestingOwner: KeyPair,
64+
filter: AccountFilter? = null,
6365
): AccountService.GetTokenAccountInfosResponse {
6466
val request = AccountService.GetTokenAccountInfosRequest.newBuilder()
6567
.setOwner(accountOwner.asSolanaAccountId())
6668
.setRequestingOwner(requestingOwner.asSolanaAccountId())
69+
.apply {
70+
if (filter != null) {
71+
when (filter) {
72+
is AccountFilter.AccountType -> {
73+
setFilterByAccountType(filter.accountType.getAccountType())
74+
}
75+
is AccountFilter.TokenAddress -> {
76+
setFilterByTokenAddress(filter.tokenAddress.asSolanaAccountId())
77+
}
78+
}
79+
}
80+
}
6781
.apply {
6882
val ownerSig = sign(accountOwner)
6983
val requestingOwnerSig = sign(requestingOwner)

services/opencode/src/main/kotlin/com/getcode/opencode/internal/network/services/AccountService.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.codeinc.opencode.gen.account.v1.AccountService
44
import com.getcode.ed25519.Ed25519.KeyPair
55
import com.getcode.opencode.internal.network.api.AccountApi
66
import com.getcode.opencode.internal.network.extensions.foldWithSuppression
7+
import com.getcode.opencode.model.accounts.AccountFilter
78
import com.getcode.opencode.model.accounts.AccountInfo
89
import com.getcode.opencode.model.accounts.AccountResponse
910
import com.getcode.opencode.model.core.errors.CodeAccountCheckError
@@ -39,9 +40,10 @@ internal class AccountService @Inject constructor(
3940
suspend fun getAccounts(
4041
accountOwner: KeyPair,
4142
requestingOwner: KeyPair,
43+
filter: AccountFilter? = null,
4244
): Result<AccountResponse> {
4345
return runCatching {
44-
api.getTokenAccounts(accountOwner, requestingOwner)
46+
api.getTokenAccounts(accountOwner, requestingOwner, filter)
4547
}.foldWithSuppression(
4648
onSuccess = { response ->
4749
when (response.result) {
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.getcode.opencode.model.accounts
2+
3+
import com.getcode.solana.keys.PublicKey
4+
5+
sealed interface AccountFilter {
6+
data class TokenAddress(val tokenAddress: PublicKey) : AccountFilter
7+
data class AccountType(val accountType: com.getcode.opencode.model.accounts.AccountType) : AccountFilter
8+
}

0 commit comments

Comments
 (0)