Skip to content

Commit

Permalink
Improve consistency of TokenIcons and fix Opensea feed
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesSmartCell committed Mar 10, 2024
1 parent 5a94f89 commit 809de30
Show file tree
Hide file tree
Showing 39 changed files with 585 additions and 415 deletions.
19 changes: 2 additions & 17 deletions app/src/main/java/com/alphawallet/app/C.java
Original file line number Diff line number Diff line change
Expand Up @@ -313,23 +313,8 @@ public enum TokenStatus {

// OpenSea APIs
public static final String OPENSEA_COLLECTION_API_MAINNET = "https://api.opensea.io/collection/";

public static final String OPENSEA_ASSETS_API_MAINNET = "https://api.opensea.io/api/v1/assets";
public static final String OPENSEA_ASSETS_API_TESTNET = "https://testnets-api.opensea.io/api/v1/assets";
public static final String OPENSEA_ASSETS_API_MATIC = "https://api.opensea.io/api/v2/assets/matic";
public static final String OPENSEA_ASSETS_API_ARBITRUM = "https://api.opensea.io/api/v2/assets/arbitrum";
public static final String OPENSEA_ASSETS_API_AVALANCHE = "https://api.opensea.io/api/v2/assets/avalanche";
public static final String OPENSEA_ASSETS_API_KLAYTN = "https://api.opensea.io/api/v2/assets/klaytn";
public static final String OPENSEA_ASSETS_API_OPTIMISM = "https://api.opensea.io/api/v2/assets/optimism";

public static final String OPENSEA_SINGLE_ASSET_API_MAINNET = "https://api.opensea.io/api/v1/asset/";
public static final String OPENSEA_SINGLE_ASSET_API_TESTNET = "https://testnets-api.opensea.io/api/v1/asset/";
public static final String OPENSEA_SINGLE_ASSET_API_MATIC = "https://api.opensea.io/api/v2/metadata/matic/";
public static final String OPENSEA_SINGLE_ASSET_API_ARBITRUM = "https://api.opensea.io/api/v2/metadata/arbitrum/";
public static final String OPENSEA_SINGLE_ASSET_API_AVALANCHE = "https://api.opensea.io/api/v2/metadata/avalanche/";
public static final String OPENSEA_SINGLE_ASSET_API_KLAYTN = "https://api.opensea.io/api/v2/metadata/klaytn/";
public static final String OPENSEA_SINGLE_ASSET_API_OPTIMISM = "https://api.opensea.io/api/v2/metadata/optimism/";

public static final String OPENSEA_ASSETS_API_V2 = "https://api.opensea.io/api/v2/chain/{CHAIN}/account/{ADDRESS}/nfts";
public static final String OPENSEA_NFT_API_V2 = "https://api.opensea.io/api/v2/chain/{CHAIN}/contract/{ADDRESS}/nfts/{TOKEN_ID}";

//Timing
public static long CONNECT_TIMEOUT = 10; //Seconds
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ public Single<List<String>> getScriptFileURI()
return Single.fromCallable(() -> callSmartContractFuncAdaptiveArray(token.tokenInfo.chainId, getScriptURI(), token.getAddress(), token.getWallet())).observeOn(Schedulers.io());
}

public Single<String> getContractURIResult()
{
return Single.fromCallable(() -> callSmartContractFunction(token.tokenInfo.chainId, getContractURI(), token.getAddress(), token.getWallet()))
.map(this::loadMetaData)
.observeOn(Schedulers.io());
}

private String loadMetaData(String tokenURI)
{
if (TextUtils.isEmpty(tokenURI))
Expand All @@ -65,7 +72,7 @@ public NFTAsset fetchTokenMetadata(BigInteger tokenId)
{
//1. get TokenURI (check for non-standard URI - check "tokenURI" and "uri")
String responseValue = callSmartContractFunction(token.tokenInfo.chainId, getTokenURI(tokenId), token.getAddress(), token.getWallet());
if (responseValue == null)
if (TextUtils.isEmpty(responseValue))
{
responseValue = callSmartContractFunction(token.tokenInfo.chainId, getTokenURI2(tokenId), token.getAddress(), token.getWallet());
}
Expand Down Expand Up @@ -102,6 +109,12 @@ private static Function getScriptURI() {
Collections.singletonList(new TypeReference<Utf8String>() {}));
}

private static Function getContractURI() {
return new Function("contractURI",
Collections.emptyList(),
Collections.singletonList(new TypeReference<Utf8String>() {}));
}

private static void setupClient()
{
if (client == null)
Expand Down
15 changes: 15 additions & 0 deletions app/src/main/java/com/alphawallet/app/entity/ImageEntry.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.alphawallet.app.entity;

public class ImageEntry
{
final public long chainId;
final public String address;
final public String imageUrl;

public ImageEntry(long networkId, String address, String imageUrl)
{
this.chainId = networkId;
this.address = address;
this.imageUrl = imageUrl;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,13 @@ public NFTAsset[] newArray(int size)
};
private static final String LOADING_TOKEN = "*Loading*";
private static final String ID = "id";
private static final String OPENSEA_ID = "identifier";
private static final String ATTN_ID = "attn_id";
private static final String NAME = "name";
private static final String IMAGE = "image";
private static final String IMAGE_URL = "image_url";
private static final String IMAGE_PREVIEW = "image_preview_url";
private static final String COLLECTION = "collection";
private static final String DESCRIPTION = "description";
private static final String IMAGE_ORIGINAL_URL = "image_original_url";
private static final String IMAGE_ANIMATION = "animation_url";
Expand All @@ -66,7 +68,7 @@ public NFTAsset[] newArray(int size)
private static final String[] IMAGE_THUMBNAIL_DESIGNATORS = {IMAGE_PREVIEW, IMAGE, IMAGE_URL, IMAGE_ORIGINAL_URL, IMAGE_ANIMATION};
private static final String BACKGROUND_COLOUR = "background_color";
private static final String EXTERNAL_LINK = "external_link";
private static final List<String> DESIRED_PARAMS = Arrays.asList(NAME, BACKGROUND_COLOUR, IMAGE_URL, IMAGE, IMAGE_ORIGINAL_URL, IMAGE_PREVIEW, DESCRIPTION, EXTERNAL_LINK, IMAGE_ANIMATION);
private static final List<String> DESIRED_PARAMS = Arrays.asList(NAME, BACKGROUND_COLOUR, IMAGE_URL, IMAGE, IMAGE_ORIGINAL_URL, IMAGE_PREVIEW, DESCRIPTION, EXTERNAL_LINK, IMAGE_ANIMATION, COLLECTION);
private static final List<String> ATTRIBUTE_DESCRIPTOR = Arrays.asList("attributes", "traits");
private final Map<String, String> assetMap = new HashMap<>();
private final Map<String, String> attributeMap = new HashMap<>();
Expand Down Expand Up @@ -265,14 +267,19 @@ private void loadFromMetaData(String metaData)
try
{
JSONObject jsonData = new JSONObject(metaData);
if (jsonData.has("nft"))
{
//need to unwrap this return value
jsonData = jsonData.getJSONObject("nft");
}
Iterator<String> keys = jsonData.keys();
String id = null;

while (keys.hasNext())
{
String key = keys.next();
String value = jsonData.getString(key);
if (key.equals(ID))
if (key.equals(ID) || key.equals(OPENSEA_ID))
{
id = value;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,22 @@ && getNFTTokenId(tokenId).compareTo(BigInteger.valueOf(0xFFFF)) < 0
&& getNFTTokenId(tokenId).compareTo(BigInteger.ZERO) > 0;
}

@Override
public String getFirstImageUrl()
{
if (assets != null && !assets.isEmpty() && assets.values().stream().findFirst().isPresent())
{
//get first asset
NFTAsset firstAsset = assets.values().stream().findFirst().get();
if (firstAsset.hasImageAsset())
{
return firstAsset.getThumbnail();
}
}

return "";
}

@Override
public boolean isBatchTransferAvailable()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ private void updateEnumerableBalance(Web3j web3j, Realm realm) throws IOExceptio
{
// find tokenId from index
String tokenId = callSmartContractFunction(tokenInfo.chainId, tokenOfOwnerByIndex(BigInteger.valueOf(tokenIndex)), getAddress(), getWallet());
if (tokenId == null) continue;
if (TextUtils.isEmpty(tokenId)) continue;
tokenIdsHeld.add(new BigInteger(tokenId));
}
}
Expand Down Expand Up @@ -620,7 +620,7 @@ private HashSet<BigInteger> checkBalances(Web3j web3j, HashSet<BigInteger> event
for (BigInteger tokenId : eventIds)
{
String owner = callSmartContractFunction(tokenInfo.chainId, ownerOf(tokenId), getAddress(), getWallet());
if (owner == null || owner.equalsIgnoreCase(getWallet()))
if (TextUtils.isEmpty(owner) || owner.equalsIgnoreCase(getWallet()))
{
heldTokens.add(tokenId);
}
Expand Down Expand Up @@ -728,6 +728,22 @@ public EthFilter getSendBalanceFilter(Event event, DefaultBlockParameter startBl
return filter;
}

@Override
public String getFirstImageUrl()
{
if (tokenBalanceAssets != null && !tokenBalanceAssets.isEmpty() && tokenBalanceAssets.values().stream().findFirst().isPresent())
{
//get first asset
NFTAsset firstAsset = tokenBalanceAssets.values().stream().findFirst().get();
if (firstAsset.hasImageAsset())
{
return firstAsset.getThumbnail();
}
}

return "";
}

public String getTransferID(Transaction tx)
{
if (tx.transactionInput != null && tx.transactionInput.miscData.size() > 0)
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/java/com/alphawallet/app/entity/tokens/Token.java
Original file line number Diff line number Diff line change
Expand Up @@ -1083,6 +1083,11 @@ public Single<List<String>> getScriptURI()
return contractInteract.getScriptFileURI();
}

public Single<String> getContractURI()
{
return contractInteract.getContractURIResult();
}

/**
* Event filters for send and receive of the token, overriden by the token type
*/
Expand Down Expand Up @@ -1153,4 +1158,9 @@ public String getAttestationCollectionId(TokenDefinition td)
{
return getTSKey();
}

public String getFirstImageUrl()
{
return "";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ public void setPostNotificationsPermissionRequested(String address, boolean hasR
@Override
public boolean getUseTSViewer()
{
return pref.getBoolean(USE_TOKENSCRIPT_VIEWER, true);
return pref.getBoolean(USE_TOKENSCRIPT_VIEWER, false);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import android.util.Pair;

import com.alphawallet.app.entity.ContractType;
import com.alphawallet.app.entity.ImageEntry;
import com.alphawallet.app.entity.Wallet;
import com.alphawallet.app.entity.nftassets.NFTAsset;
import com.alphawallet.app.entity.tokendata.TokenGroup;
Expand Down Expand Up @@ -38,7 +39,7 @@ public interface TokenLocalSource

void deleteRealmTokens(Wallet wallet, List<TokenCardMeta> tcmList);

void storeTokenUrl(long chainId, String address, String imageUrl);
void storeTokenUrl(List<ImageEntry> entries);

Token initNFTAssets(Wallet wallet, Token tokens);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.alphawallet.app.C;
import com.alphawallet.app.entity.ContractLocator;
import com.alphawallet.app.entity.ContractType;
import com.alphawallet.app.entity.ImageEntry;
import com.alphawallet.app.entity.NetworkInfo;
import com.alphawallet.app.entity.TransferFromEventResponse;
import com.alphawallet.app.entity.Wallet;
Expand Down Expand Up @@ -1295,9 +1296,9 @@ public Single<Boolean> fetchIsRedeemed(Token token, BigInteger tokenId)
}

@Override
public void addImageUrl(long networkId, String address, String imageUrl)
public void addImageUrl(List<ImageEntry> entries)
{
localSource.storeTokenUrl(networkId, address, imageUrl);
localSource.storeTokenUrl(entries);
}

public static Web3j getWeb3jServiceForEvents(long chainId)
Expand Down Expand Up @@ -1358,7 +1359,7 @@ public static String callSmartContractFunction(long chainId,
//
}

return null;
return "";
}

public static List<String> callSmartContractFuncAdaptiveArray(long chainId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import com.alphawallet.app.entity.ContractLocator;
import com.alphawallet.app.entity.ContractType;
import com.alphawallet.app.entity.ImageEntry;
import com.alphawallet.app.entity.TransferFromEventResponse;
import com.alphawallet.app.entity.Wallet;
import com.alphawallet.app.entity.nftassets.NFTAsset;
Expand Down Expand Up @@ -66,7 +67,7 @@ public interface TokenRepositoryType

Single<Boolean> fetchIsRedeemed(Token token, BigInteger tokenId);

void addImageUrl(long chainId, String address, String imageUrl);
void addImageUrl(List<ImageEntry> entries);

void updateLocalAddress(String walletAddress);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import com.alphawallet.app.entity.ContractType;
import com.alphawallet.app.entity.CustomViewSettings;
import com.alphawallet.app.entity.ImageEntry;
import com.alphawallet.app.entity.NetworkInfo;
import com.alphawallet.app.entity.Wallet;
import com.alphawallet.app.entity.nftassets.NFTAsset;
Expand Down Expand Up @@ -717,31 +718,29 @@ public Single<TokenInfo> storeTokenInfo(Wallet wallet, TokenInfo tInfo, Contract
}

@Override
public void storeTokenUrl(long networkId, String address, String imageUrl)
public void storeTokenUrl(List<ImageEntry> entries)
{
try (Realm realm = realmManager.getRealmInstance(IMAGES_DB))
{
final String instanceKey = address.toLowerCase() + "-" + networkId;
final RealmAuxData instance = realm.where(RealmAuxData.class).equalTo("instanceKey", instanceKey).findFirst();
realm.executeTransaction(r -> {
for (ImageEntry thisEntry : entries)
{
final String instanceKey = thisEntry.address.toLowerCase() + "-" + thisEntry.chainId;
RealmAuxData instance = r.where(RealmAuxData.class).equalTo("instanceKey", instanceKey).findFirst();

if (instance == null || !instance.getResult().equals(imageUrl))
{
realm.executeTransactionAsync(r -> {
RealmAuxData aux;
if (instance == null)
if (instance == null || !instance.getResult().equals(thisEntry.imageUrl))
{
aux = r.createObject(RealmAuxData.class, instanceKey);
}
else
{
aux = instance;
}
if (instance == null)
{
instance = r.createObject(RealmAuxData.class, instanceKey);
}

aux.setResult(imageUrl);
aux.setResultTime(System.currentTimeMillis());
r.insertOrUpdate(aux);
});
}
instance.setResult(thisEntry.imageUrl);
instance.setResultTime(System.currentTimeMillis());
r.insertOrUpdate(instance);
}
}
});
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3148,56 +3148,6 @@ public void storeTokenViewHeight(long chainId, String address, int listViewHeigh
}
}

public String getTokenImageUrl(long networkId, String address)
{
String url = "";
String instanceKey = address.toLowerCase() + "-" + networkId;
try (Realm realm = realmManager.getRealmInstance(IMAGES_DB))
{
RealmAuxData instance = realm.where(RealmAuxData.class)
.equalTo("instanceKey", instanceKey)
.findFirst();

if (instance != null)
{
url = instance.getResult();
}
}
catch (Exception ex)
{
Timber.e(ex);
}

return url;
}

public Pair<String, Boolean> getFallbackUrlForToken(Token token)
{
boolean storedOverride = false;
String correctedAddr = Keys.toChecksumAddress(token.getAddress());

String tURL = getTokenImageUrl(token.tokenInfo.chainId, token.getAddress());
if (TextUtils.isEmpty(tURL))
{
tURL = Utils.getTWTokenImageUrl(token.tokenInfo.chainId, correctedAddr);
}
else
{
storedOverride = true;
}

return new Pair<>(tURL, storedOverride);
}

public void storeImageUrl(long chainId, String imageUrl)
{
String tokenAddress = Utils.getTokenAddrFromAWUrl(imageUrl);
if (!TextUtils.isEmpty(tokenAddress))
{
tokensService.addTokenImageUrl(chainId, tokenAddress, imageUrl);
}
}

public Single<Integer> fetchViewHeight(long chainId, String address)
{
return Single.fromCallable(() -> {
Expand Down
Loading

0 comments on commit 809de30

Please sign in to comment.