diff --git a/apps/flipcash/shared/onramp/deeplinks/src/main/kotlin/com/flipcash/app/onramp/PhantomWalletController.kt b/apps/flipcash/shared/onramp/deeplinks/src/main/kotlin/com/flipcash/app/onramp/PhantomWalletController.kt index 9e55c326b..2e33c2ae8 100644 --- a/apps/flipcash/shared/onramp/deeplinks/src/main/kotlin/com/flipcash/app/onramp/PhantomWalletController.kt +++ b/apps/flipcash/shared/onramp/deeplinks/src/main/kotlin/com/flipcash/app/onramp/PhantomWalletController.kt @@ -22,9 +22,9 @@ import com.getcode.solana.keys.Signature import com.getcode.solana.keys.base58 import com.getcode.solana.rpc.RpcConfig import com.getcode.solana.rpc.RpcException -import com.getcode.solana.rpc.SolanaConnection import com.getcode.solana.rpc.getBalance import com.getcode.solana.rpc.getAccountData +import com.getcode.solana.rpc.getLatestBlockhash import com.getcode.solana.rpc.getTokenAccountBalance import com.getcode.solana.rpc.sendTransaction import com.getcode.solana.rpc.simulateTransaction @@ -57,7 +57,6 @@ class PhantomWalletController @Inject constructor( private val phantomSdk: PhantomSdk, private val phantomConnector: PhantomWalletConnector, ) { - private val connection by lazy { SolanaConnection(rpcConfig.rpcUrl) } private val driver by lazy { Rpc20Driver(rpcConfig.rpcUrl, rpcConfig.networkDriver) } suspend fun connectWallet( @@ -226,7 +225,7 @@ class PhantomWalletController @Inject constructor( val owner = requireNotNull(userManager.accountCluster) { "Owner is null" } val swapId = SwapId.generate() - val recentBlockhash = connection.getLatestBlockhash() + val recentBlockhash = driver.getLatestBlockhash().getOrThrow() val liquidityPool = userFlags.resolvedFlags.value.usdcOnRampLiquidityPool.effectiveValue val swapPool = when (liquidityPool) { @@ -279,7 +278,7 @@ class PhantomWalletController @Inject constructor( ): Result { return withContext(Dispatchers.IO) { try { - val recentBlockhash = connection.getLatestBlockhash() + val recentBlockhash = driver.getLatestBlockhash().getOrThrow() val poolAddress = FundSwapPool.CoinbaseStableSwapper.poolAddress val poolData = driver.getAccountData(poolAddress).getOrThrow() diff --git a/libs/crypto/solana/build.gradle.kts b/libs/crypto/solana/build.gradle.kts index a1114b89a..006048401 100644 --- a/libs/crypto/solana/build.gradle.kts +++ b/libs/crypto/solana/build.gradle.kts @@ -23,7 +23,6 @@ dependencies { implementation(libs.okhttp) implementation(libs.okhttp.logging.interceptor) - implementation("org.sol4k:sol4k:0.5.17") api("com.solanamobile:web3-solana:0.2.5") api("com.solanamobile:rpc-core:0.2.9") implementation("com.solanamobile:rpc-okiodriver:0.2.9") diff --git a/libs/crypto/solana/src/main/kotlin/com/getcode/solana/inject/SolanaModule.kt b/libs/crypto/solana/src/main/kotlin/com/getcode/solana/inject/SolanaModule.kt index a1390daa6..8a77b8656 100644 --- a/libs/crypto/solana/src/main/kotlin/com/getcode/solana/inject/SolanaModule.kt +++ b/libs/crypto/solana/src/main/kotlin/com/getcode/solana/inject/SolanaModule.kt @@ -8,7 +8,6 @@ import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import okhttp3.OkHttpClient -import org.sol4k.RpcUrl import javax.inject.Named import javax.inject.Singleton @@ -16,6 +15,8 @@ import javax.inject.Singleton @InstallIn(SingletonComponent::class) object SolanaModule { + private const val MAINNET_RPC_URL = "https://api.mainnet-beta.solana.com" + @Singleton @Provides fun providesOkRpcDriver( @@ -24,7 +25,7 @@ object SolanaModule { @Provides @Named("solana-rpc-url") - fun providesSolanaRpcUrl(): String = RpcUrl.MAINNNET.value + fun providesSolanaRpcUrl(): String = MAINNET_RPC_URL @Provides @Singleton diff --git a/libs/crypto/solana/src/main/kotlin/com/getcode/solana/rpc/Calls.kt b/libs/crypto/solana/src/main/kotlin/com/getcode/solana/rpc/Calls.kt index 448202e98..fd0332cac 100644 --- a/libs/crypto/solana/src/main/kotlin/com/getcode/solana/rpc/Calls.kt +++ b/libs/crypto/solana/src/main/kotlin/com/getcode/solana/rpc/Calls.kt @@ -8,12 +8,27 @@ import kotlinx.serialization.json.jsonArray import kotlinx.serialization.json.jsonObject import kotlinx.serialization.json.jsonPrimitive import kotlinx.serialization.json.long -import org.sol4k.Connection import android.util.Base64 -class SolanaConnection(rpcUrl: String,) { - private val connection = Connection(rpcUrl) - fun getLatestBlockhash(): String = connection.getLatestBlockhash() +/** + * Returns the most recent blockhash as a base58 string. + */ +suspend fun Rpc20Driver.getLatestBlockhash(): Result { + val response = runCatching { + makeRequest( + request = GetLatestBlockhash(), + resultSerializer = JsonElement.serializer() + ) + }.getOrElse { return Result.failure(it) } + response.error?.let { return Result.failure(RpcException(it.code, it.message)) } + + val blockhash = response.result + ?.jsonObject?.get("value") + ?.jsonObject?.get("blockhash") + ?.jsonPrimitive?.content + ?: return Result.failure(Throwable("Missing blockhash")) + + return Result.success(blockhash) } /** diff --git a/libs/crypto/solana/src/main/kotlin/com/getcode/solana/rpc/Requests.kt b/libs/crypto/solana/src/main/kotlin/com/getcode/solana/rpc/Requests.kt index 90abb4070..de312422e 100644 --- a/libs/crypto/solana/src/main/kotlin/com/getcode/solana/rpc/Requests.kt +++ b/libs/crypto/solana/src/main/kotlin/com/getcode/solana/rpc/Requests.kt @@ -64,6 +64,19 @@ internal class GetTokenAccountBalance( id = requestId ) +internal class GetLatestBlockhash( + commitment: String = "finalized", + requestId: String = "1", +): JsonRpc20Request( + method = "getLatestBlockhash", + params = buildJsonArray { + addJsonObject { + put("commitment", commitment) + } + }, + id = requestId +) + internal class SimulateTransaction( encodedTransaction: String, commitment: String = "finalized",