Skip to content

Commit

Permalink
Upgrade Token & Gas Support (#3377)
Browse files Browse the repository at this point in the history
* Enable new token discovery service, add Amoy testnet
* Add Base networks (#3378)
* Fix for not taking gas limit from Wallet Connect tx (#3379)
  • Loading branch information
JamesSmartCell authored Apr 22, 2024
1 parent e920b46 commit f3eedb5
Show file tree
Hide file tree
Showing 34 changed files with 598 additions and 75 deletions.
11 changes: 11 additions & 0 deletions app/src/main/cpp/keys.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,17 @@ Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getOkLinkKey( JNIEnv* env
#endif
}

JNIEXPORT jstring JNICALL
Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getOkLBKey( JNIEnv* env, jclass thiz )
{
#if (HAS_KEYS == 1)
return getDecryptedKey(env, oklbKey);
#else
const jstring key = "";
return (*env)->NewStringUTF(env, key);
#endif
}

JNIEXPORT jstring JNICALL
Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getBlockPiBaobabKey( JNIEnv* env, jclass thiz )
{
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/java/com/alphawallet/app/C.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ public abstract class C {
public static final String LINEA_TESTNET_NAME = LINEA_NAME + " (Test)";
public static final String HOLESKY_TESTNET_NAME = "Holesky (Test)";

public static final String AMOY_TESTNET_NAME = "Amoy (Test)";
public static final String BASE_MAINNET_NAME = "Base";
public static final String BASE_TESTNET_NAME = "Base Sepolia (Test)";

public static final String ETHEREUM_TICKER_NAME = "ethereum";
public static final String CLASSIC_TICKER_NAME = "ethereum-classic";
public static final String XDAI_TICKER_NAME = "dai";
Expand Down Expand Up @@ -91,6 +95,8 @@ public abstract class C {
public static final String ROOTSTOCK_TEST_SYMBOL = "tBTC";
public static final String HOLESKY_TEST_SYMBOL = "Hol" + ETH_SYMBOL;

public static final String AMOY_TESTNET_SYMBOL = "Am" + ETH_SYMBOL;

public static final String BURN_ADDRESS = "0x0000000000000000000000000000000000000000";

//some important known contracts - NB must be all lower case for switch statement
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import com.alphawallet.app.service.KeyService;
import com.alphawallet.app.service.KeystoreAccountService;
import com.alphawallet.app.service.NotificationService;
import com.alphawallet.app.service.OkLinkService;
import com.alphawallet.app.service.OpenSeaService;
import com.alphawallet.app.service.RealmManager;
import com.alphawallet.app.service.SwapService;
Expand Down Expand Up @@ -198,9 +199,10 @@ TokensService provideTokensServices(EthereumNetworkRepositoryType ethereumNetwor
TokenRepositoryType tokenRepository,
TickerService tickerService,
OpenSeaService openseaService,
AnalyticsServiceType analyticsService)
AnalyticsServiceType analyticsService,
OkHttpClient client)
{
return new TokensService(ethereumNetworkRepository, tokenRepository, tickerService, openseaService, analyticsService);
return new TokensService(ethereumNetworkRepository, tokenRepository, tickerService, openseaService, analyticsService, client);
}

@Singleton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ else if (chainId == GOERLI_ID || etherscanAPI.startsWith(ARBISCAN_API))
{
return new TransferFetchType[]{TransferFetchType.ERC_20, TransferFetchType.ERC_721};
}
else if (etherscanAPI.contains(MATIC_API) || etherscanAPI.contains(ETHERSCAN_API) || etherscanAPI.contains(OKX_API))
else if (etherscanAPI.contains(MATIC_API) || etherscanAPI.contains(ETHERSCAN_API) || etherscanAPI.contains(OKX_API) || etherscanAPI.contains("basescan.org"))
{
return new TransferFetchType[]{TransferFetchType.ERC_20, TransferFetchType.ERC_721, TransferFetchType.ERC_1155};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.alphawallet.app.entity.okx;

import com.alphawallet.app.entity.ContractType;

public enum OkProtocolType
{
ERC_20("token_20"),
ERC_721("token_721"),
ERC_1155("token_1155");

private final String type;

OkProtocolType(String type)
{
this.type = type;
}

public static ContractType getStandardType(OkProtocolType type)
{
switch (type)
{
case ERC_20 ->
{
return ContractType.ERC20;
}
case ERC_721 ->
{
return ContractType.ERC721;
}
case ERC_1155 ->
{
return ContractType.ERC1155;
}
}

return ContractType.ERC20;
}

public String getValue()
{
return type;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import java.util.List;

public class TransactionListResponse
public class OkServiceResponse
{
@SerializedName("code")
@Expose
Expand Down Expand Up @@ -45,5 +45,9 @@ public static class Data
@SerializedName("transactionLists")
@Expose
public List<OkxEvent> transactionLists;

@SerializedName("tokenList")
@Expose
public List<OkToken> tokenList;
}
}
33 changes: 33 additions & 0 deletions app/src/main/java/com/alphawallet/app/entity/okx/OkToken.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.alphawallet.app.entity.okx;

import com.alphawallet.app.entity.tokens.TokenInfo;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class OkToken
{
@SerializedName("symbol")
@Expose
public String symbol;

@SerializedName("tokenContractAddress")
@Expose
public String tokenContractAddress;

@SerializedName("holdingAmount")
@Expose
public String holdingAmount;

@SerializedName("priceUsd")
@Expose
public String priceUsd;

@SerializedName("tokenId")
@Expose
public String tokenId;

public TokenInfo createInfo(long chainId)
{
return new TokenInfo(tokenContractAddress, "", symbol, 0, true, chainId);
}
}
13 changes: 13 additions & 0 deletions app/src/main/java/com/alphawallet/app/entity/okx/OkTokenCheck.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.alphawallet.app.entity.okx;

public class OkTokenCheck
{
public final long chainId;
public final OkProtocolType type;

public OkTokenCheck(long chainId, OkProtocolType type)
{
this.chainId = chainId;
this.type = type;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,9 @@ public void writeToParcel(Parcel dest, int flags) {
dest.writeString(priceSymbol);
dest.writeLong(updateTime);
}

public long getTickerAgeMillis()
{
return (System.currentTimeMillis() - updateTime);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import static com.alphawallet.app.entity.EventSync.OKX_BLOCK_SEARCH_INTERVAL;
import static com.alphawallet.app.entity.EventSync.POLYGON_BLOCK_SEARCH_INTERVAL;
import static com.alphawallet.app.util.Utils.isValidUrl;
import static com.alphawallet.ethereum.EthereumNetworkBase.AMOY_TEST_RPC_URL;
import static com.alphawallet.ethereum.EthereumNetworkBase.ARBITRUM_GOERLI_TESTNET_FALLBACK_RPC_URL;
import static com.alphawallet.ethereum.EthereumNetworkBase.ARBITRUM_GOERLI_TEST_ID;
import static com.alphawallet.ethereum.EthereumNetworkBase.ARBITRUM_MAIN_ID;
Expand All @@ -16,6 +17,10 @@
import static com.alphawallet.ethereum.EthereumNetworkBase.AURORA_TESTNET_RPC_URL;
import static com.alphawallet.ethereum.EthereumNetworkBase.AVALANCHE_ID;
import static com.alphawallet.ethereum.EthereumNetworkBase.AVALANCHE_RPC_URL;
import static com.alphawallet.ethereum.EthereumNetworkBase.BASE_FREE_MAINNET_RPC;
import static com.alphawallet.ethereum.EthereumNetworkBase.BASE_FREE_TESTNET_RPC;
import static com.alphawallet.ethereum.EthereumNetworkBase.BASE_MAINNET_ID;
import static com.alphawallet.ethereum.EthereumNetworkBase.BASE_TESTNET_ID;
import static com.alphawallet.ethereum.EthereumNetworkBase.BINANCE_MAIN_ID;
import static com.alphawallet.ethereum.EthereumNetworkBase.BINANCE_TEST_ID;
import static com.alphawallet.ethereum.EthereumNetworkBase.CLASSIC_ID;
Expand Down Expand Up @@ -59,6 +64,7 @@
import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISTIC_MAIN_ID;
import static com.alphawallet.ethereum.EthereumNetworkBase.PALM_ID;
import static com.alphawallet.ethereum.EthereumNetworkBase.PALM_TEST_ID;
import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_AMOY_ID;
import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_ID;
import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_TEST_ID;
import static com.alphawallet.ethereum.EthereumNetworkBase.ROOTSTOCK_MAINNET_ID;
Expand Down Expand Up @@ -149,6 +155,17 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy
: FREE_PALM_RPC_URL;
public static final String PALM_TEST_RPC_URL = usesProductionKey ? "https://palm-testnet.infura.io/v3/" + keyProvider.getInfuraKey()
: FREE_PALM_TEST_RPC_URL;

public static final String HOLESKY_BACKUP_RPC_URL = usesProductionKey ? "https://holesky.infura.io/v3/" + keyProvider.getInfuraKey()
: "https://holesky.infura.io/v3/da3717f25f824cc1baa32d812386d93f";

public static final String AMOY_RPC = usesProductionKey ? "https://polygon-amoy.infura.io/v3/" + keyProvider.getInfuraKey()
: AMOY_TEST_RPC_URL;

public static final String AMOY_RPC_FALLBACK = usesProductionKey ? AMOY_TEST_RPC_URL : "https://polygon-amoy-bor-rpc.publicnode.com";



public static final String USE_KLAYTN_RPC = !TextUtils.isEmpty(keyProvider.getBlockPiCypressKey()) ? "https://klaytn.blockpi.network/v1/rpc/" + keyProvider.getBlockPiCypressKey()
: KLAYTN_RPC;
public static final String USE_KLAYTN_BAOBAB_RPC = !TextUtils.isEmpty(keyProvider.getBlockPiBaobabKey()) ? "https://klaytn-baobab.blockpi.network/v1/rpc/" + keyProvider.getBlockPiBaobabKey()
Expand All @@ -164,6 +181,10 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy
public static final String LINEA_FALLBACK_RPC = usesProductionKey ? LINEA_FREE_RPC : "https://linea.drpc.org";
public static final String LINEA_RPC = usesProductionKey ? "https://linea-mainnet.infura.io/v3/" + keyProvider.getInfuraKey() : LINEA_FALLBACK_RPC;
public static final String LINEA_TEST_RPC = usesProductionKey ? "https://linea-goerli.infura.io/v3/" + keyProvider.getInfuraKey() : LINEA_TEST_FREE_RPC;
public static final String BASE_RPC = usesProductionKey ? "https://base-mainnet.infura.io/v3/" + keyProvider.getInfuraKey() : BASE_FREE_MAINNET_RPC;
public static final String BASE_FALLBACK_RPC = usesProductionKey ? BASE_FREE_MAINNET_RPC : "https://base-mainnet.public.blastapi.io";
public static final String BASE_TEST_RPC = usesProductionKey ? "https://base-sepolia.infura.io/v3/" + keyProvider.getInfuraKey() : BASE_FREE_TESTNET_RPC;
public static final String BASE_TEST_FALLBACK_RPC = usesProductionKey ? BASE_FREE_TESTNET_RPC : "https://sepolia.base.org";

//Note that AlphaWallet now uses a double node configuration. See class AWHttpService comment 'try primary node'.
//If you supply a main RPC and secondary it will try the secondary if the primary node times out after 10 seconds.
Expand All @@ -188,17 +209,18 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy
//If your wallet prioritises xDai for example, you may want to move the XDAI_ID to the front of this list,
//Then xDai would appear as the first token at the top of the wallet
private static final List<Long> hasValue = new ArrayList<>(Arrays.asList(
MAINNET_ID, GNOSIS_ID, POLYGON_ID, ROOTSTOCK_MAINNET_ID, CLASSIC_ID, LINEA_ID, BINANCE_MAIN_ID, HECO_ID, AVALANCHE_ID,
MAINNET_ID, GNOSIS_ID, POLYGON_ID, ROOTSTOCK_MAINNET_ID, CLASSIC_ID, LINEA_ID, BASE_MAINNET_ID, BINANCE_MAIN_ID, HECO_ID, AVALANCHE_ID,
FANTOM_ID, OPTIMISTIC_MAIN_ID, CRONOS_MAIN_ID, ARBITRUM_MAIN_ID, PALM_ID, KLAYTN_ID, IOTEX_MAINNET_ID, AURORA_MAINNET_ID, MILKOMEDA_C1_ID, OKX_ID));

private static final List<Long> testnetList = new ArrayList<>(Arrays.asList(
SEPOLIA_TESTNET_ID, POLYGON_TEST_ID, HOLESKY_ID, GOERLI_ID, BINANCE_TEST_ID,
ROOTSTOCK_TESTNET_ID, CRONOS_TEST_ID, OPTIMISM_GOERLI_TEST_ID, ARBITRUM_GOERLI_TEST_ID, LINEA_TEST_ID, KLAYTN_BAOBAB_ID,
SEPOLIA_TESTNET_ID, POLYGON_AMOY_ID, HOLESKY_ID, BASE_TESTNET_ID, GOERLI_ID, BINANCE_TEST_ID,
ROOTSTOCK_TESTNET_ID, CRONOS_TEST_ID, OPTIMISM_GOERLI_TEST_ID, POLYGON_TEST_ID, ARBITRUM_GOERLI_TEST_ID, LINEA_TEST_ID, KLAYTN_BAOBAB_ID,
FANTOM_TEST_ID, IOTEX_TESTNET_ID, FUJI_TEST_ID, MILKOMEDA_C1_TEST_ID,
AURORA_TESTNET_ID, PALM_TEST_ID));

private static final List<Long> deprecatedNetworkList = new ArrayList<>(Arrays.asList(
// Add deprecated testnet IDs here
POLYGON_TEST_ID, GOERLI_ID
));

private static final String INFURA_ENDPOINT = ".infura.io/v3/";
Expand All @@ -208,6 +230,11 @@ public static boolean isInfura(String rpcServerUrl)
return rpcServerUrl.contains(INFURA_ENDPOINT);
}

public static boolean isOKX(NetworkInfo networkInfo)
{
return networkInfo != null && !TextUtils.isEmpty(networkInfo.etherscanAPI) && networkInfo.etherscanAPI.startsWith("https://www.oklink.com");
}

// for reset built-in network
private static final LongSparseArray<NetworkInfo> builtinNetworkMap = new LongSparseArray<NetworkInfo>()
{
Expand Down Expand Up @@ -262,7 +289,11 @@ public static boolean isInfura(String rpcServerUrl)
put(POLYGON_TEST_ID, new NetworkInfo(C.POLYGON_TEST_NETWORK, C.POLYGON_SYMBOL,
FREE_MUMBAI_RPC_URL,
"https://mumbai.polygonscan.com/tx/", POLYGON_TEST_ID,
MUMBAI_TEST_RPC_URL, " https://api-testnet.polygonscan.com/api?"));
MUMBAI_TEST_RPC_URL, "https://api-testnet.polygonscan.com/api?"));
put(POLYGON_AMOY_ID, new NetworkInfo(C.AMOY_TESTNET_NAME, C.AMOY_TESTNET_SYMBOL,
AMOY_RPC,
"https://amoy.polygonscan.com/tx/", POLYGON_AMOY_ID, AMOY_RPC_FALLBACK,
"https://api-amoy.polygonscan.com/api?"));
put(OPTIMISTIC_MAIN_ID, new NetworkInfo(C.OPTIMISTIC_NETWORK, C.ETH_SYMBOL,
OPTIMISTIC_MAIN_URL,
"https://optimistic.etherscan.io/tx/", OPTIMISTIC_MAIN_ID, OPTIMISTIC_MAIN_FALLBACK_URL,
Expand Down Expand Up @@ -342,7 +373,6 @@ public static boolean isInfura(String rpcServerUrl)
ROOTSTOCK_TESTNET_RPC_URL,
"", ROOTSTOCK_TESTNET_ID, "",
""));

put(LINEA_ID, new NetworkInfo(C.LINEA_NAME, C.ETH_SYMBOL,
LINEA_RPC,
"https://lineascan.build/tx/", LINEA_ID, LINEA_FALLBACK_RPC,
Expand All @@ -353,8 +383,16 @@ public static boolean isInfura(String rpcServerUrl)
"https://api-testnet.lineascan.build/api?"));
put(HOLESKY_ID, new NetworkInfo(C.HOLESKY_TESTNET_NAME, C.HOLESKY_TEST_SYMBOL,
HOLESKY_RPC_URL,
"https://holesky.etherscan.io/tx/", HOLESKY_ID, HOLESKY_FALLBACK_URL,
"https://holesky.etherscan.io/tx/", HOLESKY_ID, HOLESKY_BACKUP_RPC_URL,
"https://api-holesky.etherscan.io/api?"));
put(BASE_MAINNET_ID, new NetworkInfo(C.BASE_MAINNET_NAME, C.ETH_SYMBOL,
BASE_RPC,
"https://basescan.org/tx/", BASE_MAINNET_ID, BASE_FALLBACK_RPC,
"https://api.basescan.org/api?"));
put(BASE_TESTNET_ID, new NetworkInfo(C.BASE_TESTNET_NAME, C.ETH_SYMBOL,
BASE_TEST_RPC,
"https://sepolia.basescan.org/tx/", BASE_TESTNET_ID, BASE_TEST_FALLBACK_RPC,
"https://api-sepolia.basescan.org/api?"));

// Add deprecated networks after this line
}
Expand All @@ -379,7 +417,7 @@ public static boolean isInfura(String rpcServerUrl)
put(AVALANCHE_ID, R.drawable.ic_icons_tokens_avalanche);
put(FUJI_TEST_ID, R.drawable.ic_icons_tokens_avalanche_testnet);
put(POLYGON_ID, R.drawable.ic_icons_polygon);
put(POLYGON_TEST_ID, R.drawable.ic_icons_tokens_mumbai);
put(POLYGON_AMOY_ID, R.drawable.ic_icons_tokens_mumbai);
put(OPTIMISTIC_MAIN_ID, R.drawable.ic_optimism_logo);
put(CRONOS_MAIN_ID, R.drawable.ic_cronos_mainnet);
put(CRONOS_TEST_ID, R.drawable.ic_cronos);
Expand All @@ -403,6 +441,9 @@ public static boolean isInfura(String rpcServerUrl)
put(LINEA_ID, R.drawable.ic_icons_linea);
put(LINEA_TEST_ID, R.drawable.ic_icons_linea_testnet);
put(HOLESKY_ID, R.drawable.ic_icons_holesky);
put(POLYGON_TEST_ID, R.drawable.ic_icons_tokens_mumbai);
put(BASE_MAINNET_ID, R.drawable.ic_base_logo);
put(BASE_TESTNET_ID, R.drawable.ic_base_test_logo);
}
};

Expand All @@ -421,6 +462,7 @@ public static boolean isInfura(String rpcServerUrl)
put(AVALANCHE_ID, R.drawable.ic_icons_network_avalanche);
put(FUJI_TEST_ID, R.drawable.ic_icons_tokens_avalanche_testnet);
put(POLYGON_ID, R.drawable.ic_icons_network_polygon);
put(POLYGON_AMOY_ID, R.drawable.ic_icons_tokens_mumbai);
put(POLYGON_TEST_ID, R.drawable.ic_icons_tokens_mumbai);
put(OPTIMISTIC_MAIN_ID, R.drawable.ic_icons_network_optimism);
put(CRONOS_MAIN_ID, R.drawable.ic_cronos_mainnet);
Expand All @@ -445,6 +487,8 @@ public static boolean isInfura(String rpcServerUrl)
put(LINEA_ID, R.drawable.ic_icons_linea);
put(LINEA_TEST_ID, R.drawable.ic_icons_linea_testnet);
put(HOLESKY_ID, R.drawable.ic_icons_holesky);
put(BASE_MAINNET_ID, R.drawable.ic_base_logo);
put(BASE_TESTNET_ID, R.drawable.ic_base_test_logo);
}
};

Expand All @@ -464,6 +508,7 @@ public static boolean isInfura(String rpcServerUrl)
put(FUJI_TEST_ID, R.color.avalanche_test);
put(POLYGON_ID, R.color.polygon_main);
put(POLYGON_TEST_ID, R.color.polygon_test);
put(POLYGON_AMOY_ID, R.color.polygon_test);
put(OPTIMISTIC_MAIN_ID, R.color.optimistic_main);
put(CRONOS_MAIN_ID, R.color.cronos_main);
put(CRONOS_TEST_ID, R.color.cronos_test);
Expand All @@ -487,6 +532,8 @@ public static boolean isInfura(String rpcServerUrl)
put(LINEA_ID, R.color.black);
put(LINEA_TEST_ID, R.color.pinkish_grey);
put(HOLESKY_ID, R.color.azure);
put(BASE_MAINNET_ID, R.color.base_logo);
put(BASE_TESTNET_ID, R.color.base_logo);
}
};

Expand All @@ -495,7 +542,7 @@ public static boolean isInfura(String rpcServerUrl)
// <etherscanAPI from the above list> + GAS_API
//If the gas oracle you're adding doesn't follow this spec then you'll have to change the getGasOracle method
private static final List<Long> hasGasOracleAPI = Arrays.asList(MAINNET_ID, POLYGON_ID, ARBITRUM_MAIN_ID, AVALANCHE_ID, BINANCE_MAIN_ID, CRONOS_MAIN_ID, GOERLI_ID,
SEPOLIA_TESTNET_ID, FANTOM_ID, LINEA_ID, OPTIMISTIC_MAIN_ID, POLYGON_TEST_ID);
SEPOLIA_TESTNET_ID, FANTOM_ID, LINEA_ID, OPTIMISTIC_MAIN_ID, POLYGON_TEST_ID, POLYGON_AMOY_ID, BASE_MAINNET_ID, BASE_TESTNET_ID);
private static final List<Long> hasEtherscanGasOracleAPI = Arrays.asList(MAINNET_ID, HECO_ID, BINANCE_MAIN_ID, POLYGON_ID);
private static final List<Long> hasBlockNativeGasOracleAPI = Arrays.asList(MAINNET_ID, POLYGON_ID);
//These chains don't allow custom gas
Expand Down Expand Up @@ -1290,7 +1337,7 @@ public static String getChainSymbol(long chainId)

public static boolean isEventBlockLimitEnforced(long chainId)
{
if (chainId == POLYGON_ID || chainId == POLYGON_TEST_ID)
if (chainId == POLYGON_ID || chainId == POLYGON_TEST_ID || chainId == POLYGON_AMOY_ID)
{
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ public interface KeyProvider

String getOkLinkKey();

String getOkLBKey();

String getBlockPiBaobabKey();

String getBlockPiCypressKey();
Expand Down
Loading

0 comments on commit f3eedb5

Please sign in to comment.