diff --git a/app/src/main/java/com/alphawallet/app/entity/StandardFunctionInterface.java b/app/src/main/java/com/alphawallet/app/entity/StandardFunctionInterface.java index fc9bb45ec5..68fb9eb15b 100644 --- a/app/src/main/java/com/alphawallet/app/entity/StandardFunctionInterface.java +++ b/app/src/main/java/com/alphawallet/app/entity/StandardFunctionInterface.java @@ -28,4 +28,6 @@ default void handleTokenScriptFunction(String function, List selecti default void showWaitSpinner(boolean show) { } default void handleFunctionDenied(String denialMessage) { } + + default void completeFunctionSetup() { } } diff --git a/app/src/main/java/com/alphawallet/app/entity/TSAttrCallback.java b/app/src/main/java/com/alphawallet/app/entity/TSAttrCallback.java new file mode 100644 index 0000000000..3da0ab460c --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/entity/TSAttrCallback.java @@ -0,0 +1,10 @@ +package com.alphawallet.app.entity; + +import com.alphawallet.token.entity.TokenScriptResult; + +import java.util.List; + +public interface TSAttrCallback +{ + void showTSAttributes(List attrs, boolean updateRequired); +} diff --git a/app/src/main/java/com/alphawallet/app/entity/UpdateType.java b/app/src/main/java/com/alphawallet/app/entity/UpdateType.java new file mode 100644 index 0000000000..ee613771cb --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/entity/UpdateType.java @@ -0,0 +1,8 @@ +package com.alphawallet.app.entity; + +public enum UpdateType +{ + USE_CACHE, + UPDATE_IF_REQUIRED, + ALWAYS_UPDATE +} diff --git a/app/src/main/java/com/alphawallet/app/entity/tokenscript/TokenscriptFunction.java b/app/src/main/java/com/alphawallet/app/entity/tokenscript/TokenscriptFunction.java index bc900533cd..a33568094b 100644 --- a/app/src/main/java/com/alphawallet/app/entity/tokenscript/TokenscriptFunction.java +++ b/app/src/main/java/com/alphawallet/app/entity/tokenscript/TokenscriptFunction.java @@ -5,6 +5,7 @@ import android.text.TextUtils; +import com.alphawallet.app.entity.UpdateType; import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.repository.TokenRepository; import com.alphawallet.app.util.BalanceUtils; @@ -874,7 +875,8 @@ else if (!TextUtils.isEmpty(element.value)) } else { - return fetchAttrResult(token, attr, tokenId, definition, attrIf, ViewType.VIEW).blockingGet().text; + return fetchAttrResult(token, attr, tokenId, definition, attrIf, + ViewType.VIEW, UpdateType.ALWAYS_UPDATE).blockingGet().text; } return null; @@ -903,7 +905,8 @@ else if (!TextUtils.isEmpty(element.value)) */ public Single fetchAttrResult(Token token, Attribute attr, BigInteger tokenId, - TokenDefinition td, AttributeInterface attrIf, ViewType itemView) + TokenDefinition td, AttributeInterface attrIf, + ViewType itemView, UpdateType update) { if (attr == null) { @@ -941,8 +944,10 @@ else if (attr.function == null) // static attribute from tokenId (eg city mappi ContractAddress useAddress = new ContractAddress(attr.function); //always use the function attribute's address long lastTxUpdate = attrIf.getLastTokenUpdate(useAddress.chainId, useAddress.address); TransactionResult cachedResult = attrIf.getFunctionResult(useAddress, attr, useTokenId); //Needs to allow for multiple tokenIds + boolean shouldUseCache = checkUpdateRequired(attrIf, attr, cachedResult, update, + itemView == ViewType.ITEM_VIEW, lastTxUpdate, useAddress); - if ((itemView == ViewType.ITEM_VIEW || (!attr.isVolatile() && ((attrIf.resolveOptimisedAttr(useAddress, attr, cachedResult) || !cachedResult.needsUpdating(lastTxUpdate)))))) //can we use wallet's known data or cached value? + if (shouldUseCache) //can we use wallet's known data or cached value? { return resultFromDatabase(cachedResult, attr); } @@ -958,6 +963,27 @@ else if (attr.function == null) // static attribute from tokenId (eg city mappi } } + private boolean checkUpdateRequired(AttributeInterface attrIf, Attribute attr, + TransactionResult cachedResult, UpdateType update, + boolean isItemView, long lastTxUpdate, + ContractAddress useAddress) + { + switch (update) + { + case USE_CACHE -> { + return isItemView || !(cachedResult.resultTime == 0); //only update if no result + } + case UPDATE_IF_REQUIRED -> { + return (isItemView || (!attr.isVolatile() && ((attrIf.resolveOptimisedAttr(useAddress, attr, cachedResult) || !cachedResult.needsUpdating(lastTxUpdate))))); + } + case ALWAYS_UPDATE -> { + return isItemView; + } + } + + return true; + } + private Single getEventResult(TransactionResult txResult, Attribute attr, BigInteger tokenId, AttributeInterface attrIf) { //fetch the function diff --git a/app/src/main/java/com/alphawallet/app/service/AssetDefinitionService.java b/app/src/main/java/com/alphawallet/app/service/AssetDefinitionService.java index 0a02bf7952..3847d5f70e 100644 --- a/app/src/main/java/com/alphawallet/app/service/AssetDefinitionService.java +++ b/app/src/main/java/com/alphawallet/app/service/AssetDefinitionService.java @@ -28,6 +28,7 @@ import com.alphawallet.app.entity.FragmentMessenger; import com.alphawallet.app.entity.QueryResponse; import com.alphawallet.app.entity.TokenLocator; +import com.alphawallet.app.entity.UpdateType; import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.entity.nftassets.NFTAsset; import com.alphawallet.app.entity.tokens.Attestation; @@ -592,7 +593,7 @@ public TokenScriptResult.Attribute fetchAttrResult(ContractAddress origin, Attri if (originToken == null || td == null) return null; //produce result - return tokenscriptUtility.fetchAttrResult(originToken, attr, tokenId, td, this, ViewType.VIEW).blockingGet(); + return tokenscriptUtility.fetchAttrResult(originToken, attr, tokenId, td, this, ViewType.VIEW, UpdateType.UPDATE_IF_REQUIRED).blockingGet(); } /** @@ -2305,7 +2306,8 @@ private List getLocalAttributes(TokenDefinition td, List acti * @param token * @return map of unique tokenIds to lists of allowed functions for that ID - note that we allow the function to be displayed if it has a denial message */ - public Single>> fetchFunctionMap(Token token, @NotNull List tokenIds, ContractType type) + public Single>> fetchFunctionMap(Token token, @NotNull List tokenIds, + ContractType type, UpdateType update) { return Single.fromCallable(() -> { ActionModifier requiredActionModifier = type == ContractType.ATTESTATION ? ActionModifier.ATTESTATION : ActionModifier.NONE; @@ -2317,7 +2319,7 @@ public Single>> fetchFunctionMap(Token token, @NotN //first gather all attrs required - do this so if there's multiple actions using the same attribute for a tokenId we aren't fetching the value repeatedly List requiredAttrNames = getRequiredAttributeNames(actions, td); Map> attrResults // Map of attribute results vs tokenId - = getRequiredAttributeResults(requiredAttrNames, tokenIds, td, token); // Map of all required attribute values vs all the tokenIds + = getRequiredAttributeResults(requiredAttrNames, tokenIds, td, token, update); // Map of all required attribute values vs all the tokenIds for (BigInteger tokenId : tokenIds) { @@ -2388,7 +2390,7 @@ public String checkFunctionDenied(Token token, String actionName, List getAttributeResultsForTokenIds( return results; } - private Map> getRequiredAttributeResults(List requiredAttrNames, List tokenIds, TokenDefinition td, Token token) + private Map> getRequiredAttributeResults(List requiredAttrNames, List tokenIds, + TokenDefinition td, Token token, UpdateType update) { Map> resultSet = new HashMap<>(); for (BigInteger tokenId : tokenIds) @@ -2435,7 +2438,7 @@ private Map> getRequiredAtt Attribute attr = td.attributes.get(attrName); if (attr == null) continue; BigInteger useTokenId = td.useZeroForTokenIdAgnostic(attrName, tokenId); - TokenScriptResult.Attribute attrResult = tokenscriptUtility.fetchAttrResult(token, attr, useTokenId, td, this, ViewType.VIEW).blockingGet(); + TokenScriptResult.Attribute attrResult = tokenscriptUtility.fetchAttrResult(token, attr, useTokenId, td, this, ViewType.VIEW, update).blockingGet(); if (attrResult != null) { Map tokenIdMap = resultSet.get(useTokenId); @@ -2813,7 +2816,8 @@ public void clearResultMap() tokenscriptUtility.clearParseMaps(); } - public Observable resolveAttrs(Token token, TokenDefinition td, BigInteger tokenId, List extraAttrs, ViewType itemView) + public Observable resolveAttrs(Token token, TokenDefinition td, BigInteger tokenId, + List extraAttrs, ViewType itemView, UpdateType update) { TokenDefinition definition = td != null ? td : getAssetDefinition(token); ContractAddress cAddr = new ContractAddress(token.tokenInfo.chainId, token.tokenInfo.address); @@ -2827,7 +2831,7 @@ public Observable resolveAttrs(Token token, TokenDe List attrList = new ArrayList<>(definition.attributes.values()); if (extraAttrs != null) attrList.addAll(extraAttrs); - return resolveAttrs(token, tokenId, definition, attrList, itemView); + return resolveAttrs(token, tokenId, definition, attrList, itemView, update); } public List getAttestationAttrs(Token token, TSAction action, String attnId) @@ -2953,15 +2957,15 @@ private List getRealmItemsForUpdate(Realm realm, TokenDefiniti } private Observable resolveAttrs(Token token, BigInteger tokenId, TokenDefinition td, - List attrList, ViewType itemView) + List attrList, ViewType itemView, UpdateType update) { tokenscriptUtility.buildAttrMap(attrList); return Observable.fromIterable(attrList) .flatMap(attr -> tokenscriptUtility.fetchAttrResult(token, attr, tokenId, - td, this, itemView).toObservable()); + td, this, itemView, update).toObservable()); } - public Observable resolveAttrs(Token token, List tokenIds, List extraAttrs) + public Observable resolveAttrs(Token token, List tokenIds, List extraAttrs, UpdateType update) { TokenDefinition definition = getAssetDefinition(token); if (definition == null) @@ -2976,7 +2980,7 @@ public Observable resolveAttrs(Token token, List tokenIds) diff --git a/app/src/main/java/com/alphawallet/app/ui/FunctionActivity.java b/app/src/main/java/com/alphawallet/app/ui/FunctionActivity.java index 466dbdf336..5114cd4629 100644 --- a/app/src/main/java/com/alphawallet/app/ui/FunctionActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/FunctionActivity.java @@ -32,6 +32,7 @@ import com.alphawallet.app.entity.SignAuthenticationCallback; import com.alphawallet.app.entity.StandardFunctionInterface; import com.alphawallet.app.entity.TransactionReturn; +import com.alphawallet.app.entity.UpdateType; import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.entity.WalletType; import com.alphawallet.app.entity.nftassets.NFTAsset; @@ -219,7 +220,7 @@ private void getAttrs() //Add attestation attributes attrs.append(viewModel.addAttestationAttrs(asset, token, action)); - viewModel.getAssetDefinitionService().resolveAttrs(token, tokenIds, localAttrs) + viewModel.getAssetDefinitionService().resolveAttrs(token, tokenIds, localAttrs, UpdateType.USE_CACHE) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::onAttr, this::onError, () -> displayFunction(attrs.toString())) @@ -392,7 +393,7 @@ public void calculationCompleted(String value, String result, TokenscriptElement @Override public void unresolvedSymbolError(String value) { - Timber.d("ATTR/FA: Resolve: ERROR: " + value); + Timber.d("ATTR/FA: Resolve: ERROR: %s", value); tokenScriptError(value, null); } }; @@ -1002,13 +1003,4 @@ private void getValueFromInnerHTML(CalcJsValueCallback callback, String value, T } }); } - - private void repopulateInputField(String key, String value) - { - tokenView.evaluateJavascript( - "(function() { document.getElementById(\"" + key + "\").innerHTML = \"" + value + "\"; })();", - html -> { - Timber.d("Worked?"); - }); - } } diff --git a/app/src/main/java/com/alphawallet/app/ui/NFTAssetDetailActivity.java b/app/src/main/java/com/alphawallet/app/ui/NFTAssetDetailActivity.java index 19f36dcd0b..4920746526 100644 --- a/app/src/main/java/com/alphawallet/app/ui/NFTAssetDetailActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/NFTAssetDetailActivity.java @@ -16,7 +16,6 @@ import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.AnimationUtils; -import android.webkit.WebView; import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.TextView; @@ -35,6 +34,7 @@ import com.alphawallet.app.entity.GasEstimate; import com.alphawallet.app.entity.SignAuthenticationCallback; import com.alphawallet.app.entity.StandardFunctionInterface; +import com.alphawallet.app.entity.TSAttrCallback; import com.alphawallet.app.entity.TransactionReturn; import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.entity.WalletType; @@ -62,7 +62,6 @@ import com.alphawallet.token.entity.TSAction; import com.alphawallet.token.entity.TicketRange; import com.alphawallet.token.entity.TokenScriptResult; -import com.alphawallet.token.entity.TokenScriptResult.Attribute; import com.alphawallet.token.entity.ViewType; import com.alphawallet.token.entity.XMLDsigDescriptor; import com.alphawallet.token.tools.TokenDefinition; @@ -75,11 +74,7 @@ import java.util.Map; import dagger.hilt.android.AndroidEntryPoint; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.disposables.Disposable; import io.reactivex.functions.Consumer; -import io.reactivex.schedulers.Schedulers; -import timber.log.Timber; @AndroidEntryPoint public class NFTAssetDetailActivity extends BaseActivity implements StandardFunctionInterface, ActionSheetCallback @@ -317,7 +312,7 @@ private void setup() else { viewModel.getAsset(token, tokenId); - viewModel.updateLocalAttributes(token, tokenId); + viewModel.updateLocalAttributes(token, tokenId); //when complete calls displayTokenView } } @@ -334,7 +329,7 @@ private void initViewModel() viewModel.sig().observe(this, this::onSignature); viewModel.newScriptFound().observe(this, this::newScriptFound); viewModel.walletUpdate().observe(this, this::setupFunctionBar); - viewModel.attrFetchComplete().observe(this, this::displayTokenView); + viewModel.attrFetchComplete().observe(this, this::displayTokenView); //local attr fetch } private void newScriptFound(TokenDefinition td) @@ -412,18 +407,17 @@ private void completeAttestationTokenScriptSetup(TSAction action) } } - private void completeTokenScriptSetup() + private void completeTokenScriptSetup(String prevResult) { - final List attrs = new ArrayList<>(); - - if (viewModel.hasTokenScript(token)) - { - viewModel.getAssetDefinitionService().resolveAttrs(token, new ArrayList<>(Collections.singleton(tokenId)), null) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(attrs::add, this::onError, () -> showTSAttributes(attrs)) - .isDisposed(); - } + viewModel.completeTokenScriptSetup(token, tokenId, prevResult, (attrs, needsUpdate) -> { + //should have resolved all the attrs + tsAttributeLayout.bindTSAttributes(attrs); + //require refresh of TS View + if (needsUpdate) + { + displayTokenView(viewModel.getAssetDefinitionService().getAssetDefinition(token)); + } + }); } private void reloadMetadata() @@ -503,22 +497,9 @@ private void loadAssetFromMetadata(NFTAsset loadedAsset) clearRefreshAnimation(); loadFromOpenSeaData(loadedAsset.getOpenSeaAsset()); - - completeTokenScriptSetup(); } } - private void showTSAttributes(List attrs) - { - //should have resolved all the attrs - tsAttributeLayout.bindTSAttributes(attrs); - } - - private void onError(Throwable throwable) - { - Timber.w(throwable); - } - private void updateTokenImage(NFTAsset asset) { if (triggeredReload) tokenImage.clearImage(); @@ -626,7 +607,7 @@ private void loadFromOpenSeaData(OpenSeaAsset openSeaAsset) private void setupAttestation(TokenDefinition td) { NFTAsset attnAsset = new NFTAsset(); - if (token.getInterfaceSpec() != ContractType.ATTESTATION) + if (token == null || token.getInterfaceSpec() != ContractType.ATTESTATION) { return; } @@ -634,7 +615,7 @@ else if (td != null) { attnAsset.setupScriptElements(td); attnAsset.setupScriptAttributes(td, token); - if (!displayTokenView(td)) + if (!displayTokenView(td)) //display token for Attribute { tokenImage.setupTokenImage(attnAsset); } @@ -796,7 +777,7 @@ private void showIssuer(String issuer) if (!TextUtils.isEmpty(issuer)) { ((TokenInfoView)findViewById(R.id.key_address)).setCopyableValue(issuer); - ((TokenInfoView)findViewById(R.id.key_address)).setVisibility(View.VISIBLE); + findViewById(R.id.key_address).setVisibility(View.VISIBLE); } } @@ -848,6 +829,13 @@ public WalletType getWalletType() return viewModel.getWallet().type; } + @Override + public void completeFunctionSetup() + { + //check if TS needs to be refreshed + completeTokenScriptSetup(tokenScriptView.getAttrResults()); + } + /*** * TokenScript view handling */ diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/TokenFunctionViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/TokenFunctionViewModel.java index 61d095d887..c01a6909dc 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/TokenFunctionViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/TokenFunctionViewModel.java @@ -21,8 +21,10 @@ import com.alphawallet.app.entity.GasEstimate; import com.alphawallet.app.entity.Operation; import com.alphawallet.app.entity.SignAuthenticationCallback; +import com.alphawallet.app.entity.TSAttrCallback; import com.alphawallet.app.entity.Transaction; import com.alphawallet.app.entity.TransactionReturn; +import com.alphawallet.app.entity.UpdateType; import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.entity.WalletType; import com.alphawallet.app.entity.nftassets.NFTAsset; @@ -133,6 +135,9 @@ public class TokenFunctionViewModel extends BaseViewModel implements Transaction @Nullable private Disposable scriptUpdate; + @Nullable + private Disposable attrRefresh; + @Inject TokenFunctionViewModel( AssetDefinitionService assetDefinitionService, @@ -575,6 +580,10 @@ public void onDestroy() { scriptUpdate.dispose(); } + if (attrRefresh != null && !attrRefresh.isDisposed()) + { + attrRefresh.dispose(); + } gasService.stopGasPriceCycle(); } @@ -852,6 +861,25 @@ private void onCollection(Token token, BigInteger tokenId, NFTAsset asset, OpenS nftAsset.postValue(asset); } + public void completeTokenScriptSetup(Token token, BigInteger tokenId, String prevResult, TSAttrCallback tsCb) + { + final StringBuilder attrsTxt = new StringBuilder(); + final List attrs = new ArrayList<>(); + + if (hasTokenScript(token)) + { + attrRefresh = assetDefinitionService.resolveAttrs(token, new ArrayList<>(Collections.singleton(tokenId)), null, UpdateType.USE_CACHE) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(attr -> { attrs.add(attr); attrsTxt.append(attr.text); }, this::onError, () -> checkUpdatedAttrs(prevResult, attrsTxt, attrs, tsCb)); + } + } + + private void checkUpdatedAttrs(String prevResult, final StringBuilder attrsText, List attrs, TSAttrCallback tsCb) + { + tsCb.showTSAttributes(attrs, !prevResult.equals(attrsText.toString())); + } + private void onAssetError(Throwable throwable) { Timber.d(throwable); @@ -910,13 +938,14 @@ public boolean hasTokenScript(Token token) public void updateLocalAttributes(Token token, BigInteger tokenId) { //Fetch Allowed attributes, then call updateAllowedAttributes - assetDefinitionService.fetchFunctionMap(token, Collections.singletonList(tokenId), token.getInterfaceSpec()) + assetDefinitionService.fetchFunctionMap(token, Collections.singletonList(tokenId), token.getInterfaceSpec(), UpdateType.USE_CACHE) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(availableActions -> updateAllowedAttrs(token, availableActions), this::onError) .isDisposed(); } + /** @noinspection SimplifyOptionalCallChains*/ private void updateAllowedAttrs(Token token, Map> availableActions) { if (!availableActions.keySet().stream().findFirst().isPresent()) @@ -986,7 +1015,6 @@ public Single findWallet(String walletAddress) return genericWalletInteract.findWallet(walletAddress); } - public String addAttestationAttrs(NFTAsset asset, Token token, TSAction action) { StringBuilder attrs = new StringBuilder(); diff --git a/app/src/main/java/com/alphawallet/app/web3/Web3TokenView.java b/app/src/main/java/com/alphawallet/app/web3/Web3TokenView.java index 94389a8ca5..0b8b22010e 100644 --- a/app/src/main/java/com/alphawallet/app/web3/Web3TokenView.java +++ b/app/src/main/java/com/alphawallet/app/web3/Web3TokenView.java @@ -29,6 +29,8 @@ import com.alphawallet.app.BuildConfig; import com.alphawallet.app.R; +import com.alphawallet.app.entity.StandardFunctionInterface; +import com.alphawallet.app.entity.UpdateType; import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.entity.tokenscript.TokenScriptRenderCallback; import com.alphawallet.app.entity.tokenscript.WebCompletionCallback; @@ -57,6 +59,7 @@ import java.util.Objects; import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; import io.realm.Realm; import io.realm.RealmResults; @@ -84,12 +87,16 @@ public class Web3TokenView extends WebView private RealmResults realmAuxUpdates; protected WebCompletionCallback keyPressCallback; + @Nullable + private Disposable buildViewAttrs; @Nullable private OnSignPersonalMessageListener onSignPersonalMessageListener; @Nullable private OnSetValuesListener onSetValuesListener; + private String attrResults; + public Web3TokenView(@NonNull Context context) { super(context); init(); @@ -450,7 +457,8 @@ private void showLegacyView(Token token, TicketRange range) loadData(displayData, "text/html", "utf-8"); } - public boolean renderTokenScriptView(Token token, TicketRange range, AssetDefinitionService assetService, ViewType itemView, final TokenDefinition td) + public boolean renderTokenScriptView(Token token, TicketRange range, AssetDefinitionService assetService, ViewType itemView, + final TokenDefinition td) { BigInteger tokenId = range.tokenIds.get(0); if (!td.hasTokenView()) @@ -458,14 +466,15 @@ public boolean renderTokenScriptView(Token token, TicketRange range, AssetDefini return false; } + attrResults = ""; + final StringBuilder attrs = assetService.getTokenAttrs(token, tokenId, range.tokenIds.size()); - assetService.resolveAttrs(token, null, tokenId, assetService.getTokenViewLocalAttributes(token), itemView) + buildViewAttrs = assetService.resolveAttrs(token, null, tokenId, assetService.getTokenViewLocalAttributes(token), itemView, UpdateType.USE_CACHE) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(attr -> onAttr(attr, attrs), throwable -> onError(token, throwable, range), - () -> displayTicket(token, assetService, attrs, itemView, range, td)) - .isDisposed(); + () -> displayTokenView(token, assetService, attrs, itemView, range, td)); return true; } @@ -478,7 +487,7 @@ public boolean renderTokenScriptView(Token token, TicketRange range, AssetDefini * @param iconified * @param range */ - private void displayTicket(Token token, AssetDefinitionService assetService, StringBuilder attrs, ViewType iconified, TicketRange range, final TokenDefinition td) + private void displayTokenView(Token token, AssetDefinitionService assetService, StringBuilder attrs, ViewType iconified, TicketRange range, final TokenDefinition td) { setVisibility(View.VISIBLE); String viewName; @@ -534,6 +543,11 @@ private long getLastUpdateTime(Realm realm, Token token, BigInteger tokenId) return lastResultTime + 1; } + public String getAttrResults() + { + return attrResults; + } + @Override public void onPause() { @@ -563,6 +577,11 @@ public void destroy() realmAuxUpdates.getRealm().close(); } } + + if (buildViewAttrs != null && !buildViewAttrs.isDisposed()) + { + buildViewAttrs.dispose(); + } } /** @@ -600,5 +619,6 @@ private void onError(Token token, Throwable throwable, TicketRange range) private void onAttr(TokenScriptResult.Attribute attribute, StringBuilder attrs) { TokenScriptResult.addPair(attrs, attribute.id, attribute.text); + attrResults += attribute.text; } } diff --git a/app/src/main/java/com/alphawallet/app/widget/FunctionButtonBar.java b/app/src/main/java/com/alphawallet/app/widget/FunctionButtonBar.java index 6950134e31..fd4cfc3e93 100644 --- a/app/src/main/java/com/alphawallet/app/widget/FunctionButtonBar.java +++ b/app/src/main/java/com/alphawallet/app/widget/FunctionButtonBar.java @@ -39,6 +39,7 @@ import com.alphawallet.app.entity.ItemClick; import com.alphawallet.app.entity.OnRampContract; import com.alphawallet.app.entity.StandardFunctionInterface; +import com.alphawallet.app.entity.UpdateType; import com.alphawallet.app.entity.WalletType; import com.alphawallet.app.entity.tokens.Attestation; import com.alphawallet.app.entity.tokens.Token; @@ -698,7 +699,7 @@ private void getFunctionMap(AssetDefinitionService assetSvs, ContractType type) findViewById(R.id.wait_buttons).setVisibility(View.VISIBLE); //get the available map for this collection - assetSvs.fetchFunctionMap(token, selection, type) + assetSvs.fetchFunctionMap(token, selection, type, UpdateType.UPDATE_IF_REQUIRED) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(availabilityMap -> setupTokenMap(token, availabilityMap), this::onMapFetchError) @@ -728,6 +729,8 @@ private void setupTokenMap(@NotNull Token token, Map> a populateButtons(token, tokenId); showButtons(); } + + callStandardFunctions.completeFunctionSetup(); } private void showButtons() diff --git a/lib/src/main/java/com/alphawallet/token/entity/TransactionResult.java b/lib/src/main/java/com/alphawallet/token/entity/TransactionResult.java index 81021dabff..a00298878e 100644 --- a/lib/src/main/java/com/alphawallet/token/entity/TransactionResult.java +++ b/lib/src/main/java/com/alphawallet/token/entity/TransactionResult.java @@ -32,6 +32,6 @@ public TransactionResult(long chainId, String address, BigInteger tokenId, Attri public boolean needsUpdating(long lastTxTime) { //if contract had new transactions then update, or if last tx was -1 (always check) - return (resultTime == 0 || ((System.currentTimeMillis() + 5*10*1000) < resultTime) || lastTxTime < 0 || lastTxTime > resultTime); + return resultTime == 0 || System.currentTimeMillis() > (resultTime + 30*1000) || lastTxTime < 0 || lastTxTime > resultTime; } }