Updated on 2026-08-14
This commit is contained in:
parent
bf1c374582
commit
44c69929b2
6 changed files with 113 additions and 2 deletions
|
|
@ -40,6 +40,14 @@ public class Server {
|
|||
}
|
||||
}
|
||||
|
||||
public static class ApiInfuraRopsten {
|
||||
public static final String URL_INFURA_ROPSTEN = ServerURL.API_INFURA_ROPSTEN;
|
||||
|
||||
public static class Method {
|
||||
public static final String MAIN = "v3/613a0b14833145968b1f656240c7d245";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class ApiSoChain {
|
||||
public static final String URL = ServerURL.API_SOCHAIN_V2;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,8 @@ public class ServerApiInfura {
|
|||
public ServerApiInfura(Blockchain blockchain) {
|
||||
if (blockchain == Blockchain.EthereumTestNet) {
|
||||
infuraApi = App.Companion.getNetworkComponent().getRetrofitInfuraTestnet().create(InfuraApi.class);
|
||||
} else if (blockchain == Blockchain.TokenEmv) {
|
||||
infuraApi = App.Companion.getNetworkComponent().getRetrofitInfuraRopsten().create(InfuraApi.class);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ class ServerURL {
|
|||
static final String API_COINMARKETCAP = "https://pro-api.coinmarketcap.com/";
|
||||
static final String API_INFURA = "https://mainnet.infura.io/";
|
||||
static final String API_INFURA_TESTNET = "https://rinkeby.infura.io/";
|
||||
static final String API_INFURA_ROPSTEN = "https://ropsten.infura.io/";
|
||||
static final String API_SOCHAIN_V2 = "https://chain.so/";
|
||||
static final String API_ESTIMATEFEE = "https://estimatefee.com/";
|
||||
static final String API_UPDATE_VERSION = "https://raw.githubusercontent.com/";
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@ interface NetworkComponent {
|
|||
@get:Named(Server.ApiInfuraTestnet.URL_INFURA_TESTNET)
|
||||
val retrofitInfuraTestnet: Retrofit
|
||||
|
||||
@get:Named(Server.ApiInfuraRopsten.URL_INFURA_ROPSTEN)
|
||||
val retrofitInfuraRopsten: Retrofit
|
||||
|
||||
@get:Named(Server.ApiMaticTesnet.URL_MATIC_TESTNET)
|
||||
val retrofitMaticTesnet: Retrofit
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,18 @@ internal class NetworkModule {
|
|||
return builder.build()
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
@Named(Server.ApiInfuraRopsten.URL_INFURA_ROPSTEN)
|
||||
fun provideRetrofitInfuraRopsten(): Retrofit {
|
||||
val builder = Retrofit.Builder()
|
||||
.baseUrl(Server.ApiInfuraRopsten.URL_INFURA_ROPSTEN)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
if (BuildConfig.DEBUG)
|
||||
builder.client(createOkHttpClient())
|
||||
return builder.build()
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
@Named(Server.ApiRootstock.URL_ROOTSTOCK)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ import android.text.InputFilter
|
|||
import android.util.Log
|
||||
import com.google.gson.Gson
|
||||
import com.tangem.data.Blockchain
|
||||
import com.tangem.data.network.ServerApiInfura
|
||||
import com.tangem.data.network.ServerApiTokenEmv
|
||||
import com.tangem.data.network.model.InfuraResponse
|
||||
import com.tangem.data.network.model.TokenEmvTransferBody
|
||||
import com.tangem.tangem_card.data.TangemCard
|
||||
import com.tangem.tangem_card.reader.CardProtocol.TangemException
|
||||
|
|
@ -20,6 +22,7 @@ import org.apache.commons.lang3.SerializationUtils
|
|||
import org.bitcoinj.core.ECKey
|
||||
import org.kethereum.extensions.toBytesPadded
|
||||
import org.kethereum.extensions.toFixedLengthByteArray
|
||||
import java.math.BigDecimal
|
||||
import java.math.BigInteger
|
||||
import java.util.*
|
||||
|
||||
|
|
@ -30,13 +33,17 @@ class TokenEmvEngine : TokenEngine {
|
|||
private val TAG = TokenEmvEngine::class.java.simpleName
|
||||
|
||||
private fun hasLinkedContract(): Boolean {
|
||||
return ctx.card.issuerData != null && ctx.card.issuerData.size == 20
|
||||
return ctx.card.issuerData != null && ctx.card.issuerData.size == 44
|
||||
}
|
||||
|
||||
override fun getBlockchain(): Blockchain {
|
||||
return Blockchain.TokenEmv
|
||||
}
|
||||
|
||||
override fun getChainIdNum(): Int {
|
||||
return EthTransaction.ChainEnum.Mainnet.value
|
||||
}
|
||||
|
||||
override fun getBalance(): Amount? {
|
||||
return if (!hasBalanceInfo()) {
|
||||
null
|
||||
|
|
@ -89,7 +96,8 @@ class TokenEmvEngine : TokenEngine {
|
|||
override fun defineWallet() {
|
||||
try {
|
||||
if (hasLinkedContract()) {
|
||||
ctx.coinData.wallet = String.format("0x%s", BTCUtils.toHex(ctx.card.issuerData))
|
||||
val issuerData = ctx.card.issuerData
|
||||
ctx.coinData.wallet = String(issuerData.copyOfRange(2, issuerData.size))
|
||||
} else {
|
||||
ctx.coinData.wallet = calculateAddress(ctx.card.walletPublicKey)
|
||||
}
|
||||
|
|
@ -212,6 +220,79 @@ class TokenEmvEngine : TokenEngine {
|
|||
}
|
||||
}
|
||||
|
||||
override fun requestBalanceAndUnspentTransactions(blockchainRequestsCallbacks: BlockchainRequestsCallbacks) {
|
||||
val serverApiInfura = ServerApiInfura(ctx.blockchain)
|
||||
|
||||
val responseListener: ServerApiInfura.ResponseListener = object : ServerApiInfura.ResponseListener {
|
||||
override fun onSuccess(method: String, infuraResponse: InfuraResponse) {
|
||||
when (method) {
|
||||
ServerApiInfura.INFURA_ETH_GET_TRANSACTION_COUNT -> {
|
||||
var nonce = infuraResponse.result
|
||||
nonce = nonce!!.substring(2)
|
||||
val count = BigInteger(nonce, 16)
|
||||
coinData.confirmedTXCount = count
|
||||
if (serverApiInfura.isRequestsSequenceCompleted) { //getting balances after checking for pending to avoid showing old balance as verified
|
||||
serverApiInfura.requestData(ServerApiInfura.INFURA_ETH_CALL, 67, coinData.wallet, getContractAddress(ctx.card), "")
|
||||
}
|
||||
}
|
||||
ServerApiInfura.INFURA_ETH_GET_PENDING_COUNT -> {
|
||||
var pending = infuraResponse.result
|
||||
pending = pending!!.substring(2)
|
||||
val count = BigInteger(pending, 16)
|
||||
coinData.unconfirmedTXCount = count
|
||||
if (serverApiInfura.isRequestsSequenceCompleted) { //getting balances after checking for pending to avoid showing old balance as verified
|
||||
serverApiInfura.requestData(ServerApiInfura.INFURA_ETH_CALL, 67, coinData.wallet, getContractAddress(ctx.card), "")
|
||||
}
|
||||
}
|
||||
ServerApiInfura.INFURA_ETH_CALL -> {
|
||||
try {
|
||||
var balanceCap = infuraResponse.result
|
||||
balanceCap = balanceCap!!.substring(2)
|
||||
val l = BigInteger(balanceCap, 16)
|
||||
coinData.balanceInInternalUnits = InternalAmount(l, ctx.card.tokenSymbol)
|
||||
coinData.isBalanceReceived = true
|
||||
// Log.i("$TAG eth_call", balanceCap)
|
||||
} catch (e: java.lang.Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
if (serverApiInfura.isRequestsSequenceCompleted) {
|
||||
blockchainRequestsCallbacks.onComplete(!ctx.hasError())
|
||||
} else {
|
||||
blockchainRequestsCallbacks.onProgress()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFail(method: String, message: String) {
|
||||
Log.e(TAG, "onFail: $method $message")
|
||||
ctx.error = message
|
||||
if (serverApiInfura.isRequestsSequenceCompleted) {
|
||||
blockchainRequestsCallbacks.onComplete(false)
|
||||
} else {
|
||||
blockchainRequestsCallbacks.onProgress()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
serverApiInfura.setResponseListener(responseListener)
|
||||
|
||||
if (validateAddress(getContractAddress(ctx.card))) {
|
||||
serverApiInfura.requestData(ServerApiInfura.INFURA_ETH_GET_TRANSACTION_COUNT, 67, coinData.wallet, "", "")
|
||||
serverApiInfura.requestData(ServerApiInfura.INFURA_ETH_GET_PENDING_COUNT, 67, coinData.wallet, "", "")
|
||||
} else {
|
||||
ctx.error = "Smart contract address not defined"
|
||||
blockchainRequestsCallbacks.onComplete(false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun requestFee(blockchainRequestsCallbacks: BlockchainRequestsCallbacks, targetAddress: String?, amount: Amount) {
|
||||
val fee = Amount(BigDecimal.ONE, balanceCurrency)
|
||||
coinData.minFee = fee
|
||||
coinData.normalFee = fee
|
||||
coinData.maxFee = fee
|
||||
}
|
||||
|
||||
override fun requestSendTransaction(blockchainRequestsCallbacks: BlockchainRequestsCallbacks, txForSend: ByteArray?) {
|
||||
val jsonBody = SerializationUtils.deserialize<String>(txForSend)
|
||||
val tokenEmvTransferBody = Gson().fromJson(jsonBody, TokenEmvTransferBody::class.java)
|
||||
|
|
@ -229,6 +310,10 @@ class TokenEmvEngine : TokenEngine {
|
|||
ServerApiTokenEmv().transfer(tokenEmvTransferBody, transferObserver)
|
||||
}
|
||||
|
||||
override fun allowSelectFeeLevel(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
// TODO: move all below to the server
|
||||
fun constructTransfer(tokenEmvTransferBody: TokenEmvTransferBody, feeValue: Amount?): SignTask.TransactionToSign {
|
||||
val contractAddress = tokenEmvTransferBody.contract
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue