Add local attributes to TokenScript action view

pull/1263/head
James Brown 5 years ago
parent 5c59c5c749
commit b4e4125003
  1. 2
      app/src/main/java/com/alphawallet/app/entity/tokens/Token.java
  2. 35
      app/src/main/java/com/alphawallet/app/entity/tokenscript/TokenscriptFunction.java
  3. 25
      app/src/main/java/com/alphawallet/app/service/AssetDefinitionService.java
  4. 15
      app/src/main/java/com/alphawallet/app/ui/FunctionActivity.java
  5. 2
      app/src/main/java/com/alphawallet/app/ui/widget/holder/TokenscriptViewHolder.java
  6. 7
      dmz/src/main/java/com/alphawallet/token/web/Ethereum/TokenscriptFunction.java
  7. 8
      util/src/main/java/com/alphawallet/scripttool/Entity/TokenscriptFunction.java

@ -1089,7 +1089,7 @@ public class Token implements Parcelable, Comparable<Token>
final StringBuilder attrs = assetService.getTokenAttrs(this, tokenId, range.tokenIds.size());
assetService.resolveAttrs(this, tokenId)
assetService.resolveAttrs(this, tokenId, null) //Can a view have local attributes?
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(attr -> onAttr(attr, attrs), throwable -> onError(throwable, ctx, assetService, attrs,

@ -599,7 +599,7 @@ public abstract class TokenscriptFunction
{
if (definition != null && definition.attributeTypes.containsKey(arg.element.ref))
{
arg.element.value = fetchAttrResult(walletAddress, arg.element.ref, tokenId, null, definition, attrIf, 0).blockingSingle().text;
arg.element.value = fetchAttrResult(walletAddress, definition.attributeTypes.get(arg.element.ref), tokenId, null, definition, attrIf, 0).blockingSingle().text;
}
}
@ -618,7 +618,7 @@ public abstract class TokenscriptFunction
* any cached results. However if we're tracking the referenced contract as a token then it should be safe
*
* @param walletAddress
* @param attribute
* @param attr
* @param tokenId
* @param cAddr
* @param td
@ -626,10 +626,9 @@ public abstract class TokenscriptFunction
* @param transactionUpdate
* @return
*/
public Observable<TokenScriptResult.Attribute> fetchAttrResult(String walletAddress, String attribute, BigInteger tokenId, ContractAddress cAddr, TokenDefinition td, AttributeInterface attrIf, long transactionUpdate)
public Observable<TokenScriptResult.Attribute> fetchAttrResult(String walletAddress, AttributeType attr, BigInteger tokenId, ContractAddress cAddr, TokenDefinition td, AttributeInterface attrIf, long transactionUpdate)
{
AttributeType attr = td.attributeTypes.get(attribute);
if (attr == null || isAttrIncomplete(attr)) return Observable.fromCallable(() -> new TokenScriptResult.Attribute("bd", "bd", BigInteger.ZERO, ""));
if (attr == null) return Observable.fromCallable(() -> new TokenScriptResult.Attribute("bd", "bd", BigInteger.ZERO, ""));
if (attr.function == null) // static attribute from tokenId (eg city mapping from tokenId)
{
return staticAttribute(attr, tokenId);
@ -655,32 +654,6 @@ public abstract class TokenscriptFunction
}
}
private boolean isAttrIncomplete(AttributeType attr)
{
if (attr.function == null) return false;
for (MethodArg arg : attr.function.parameters)
{
int index = arg.getTokenIndex();
if (arg.isTokenId() && index >= 0 && (arg.element.value == null || arg.element.value.length() == 0))
{
return true;
}
}
return false;
}
public Observable<TokenScriptResult.Attribute> resolveAttributes(String walletAddress, BigInteger tokenId, AttributeInterface attrIf, ContractAddress cAddr, TokenDefinition td, long transactionUpdate)
{
td.context = new TokenscriptContext();
td.context.cAddr = cAddr;
td.context.attrInterface = attrIf;
return Observable.fromIterable(new ArrayList<>(td.attributeTypes.values()))
.flatMap(attr -> fetchAttrResult(walletAddress, attr.id, tokenId, cAddr, td, attrIf, transactionUpdate));
}
private Observable<TokenScriptResult.Attribute> staticAttribute(AttributeType attr, BigInteger tokenId)
{
return Observable.fromCallable(() -> {

@ -41,6 +41,7 @@ import com.alphawallet.token.entity.ParseResult;
import com.alphawallet.token.entity.SigReturnType;
import com.alphawallet.token.entity.TSAction;
import com.alphawallet.token.entity.TokenScriptResult;
import com.alphawallet.token.entity.TokenscriptContext;
import com.alphawallet.token.entity.TokenscriptElement;
import com.alphawallet.token.entity.TransactionResult;
import com.alphawallet.token.entity.XMLDsigDescriptor;
@ -1144,7 +1145,7 @@ public class AssetDefinitionService implements ParseResult, AttributeInterface
Observable.fromIterable(token.getNonZeroArrayBalance())
.map(tokenId -> getFunctionResult(cAddr, attr, tokenId))
.filter(txResult -> txResult.needsUpdating(token.lastTxTime))
.concatMap(result -> tokenscriptUtility.fetchAttrResult(token.getWallet(), attr.id, result.tokenId, cAddr, td, this, token.lastTxTime))
.concatMap(result -> tokenscriptUtility.fetchAttrResult(token.getWallet(), td.attributeTypes.get(attr.id), result.tokenId, cAddr, td, this, token.lastTxTime))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe();
@ -1155,7 +1156,7 @@ public class AssetDefinitionService implements ParseResult, AttributeInterface
TransactionResult tr = getFunctionResult(cAddr, attr, BigInteger.ZERO);
if (tr.needsUpdating(token.lastTxTime))
{
tokenscriptUtility.fetchAttrResult(token.getWallet(), attr.id, tr.tokenId, cAddr, td, this, token.lastTxTime)
tokenscriptUtility.fetchAttrResult(token.getWallet(), td.attributeTypes.get(attr.id), tr.tokenId, cAddr, td, this, token.lastTxTime)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe();
@ -1405,16 +1406,24 @@ public class AssetDefinitionService implements ParseResult, AttributeInterface
return sb.toString();
}
public Observable<TokenScriptResult.Attribute> resolveAttrs(Token token, BigInteger tokenId)
public Observable<TokenScriptResult.Attribute> resolveAttrs(Token token, BigInteger tokenId, List<AttributeType> extraAttrs)
{
TokenDefinition definition = getAssetDefinition(token.tokenInfo.chainId, token.tokenInfo.address);
ContractAddress cAddr = new ContractAddress(token.tokenInfo.chainId, token.tokenInfo.address);
//return definition.resolveAttributes(tokenId, this, cAddr);
//resolveAttributes(BigInteger tokenId, AttributeInterface attrIf, ContractAddress cAddr, TokenDefinition td)
return tokenscriptUtility.resolveAttributes(token.getWallet(), tokenId, this, cAddr, definition, token.lastTxTime);
definition.context = new TokenscriptContext();
definition.context.cAddr = cAddr;
definition.context.attrInterface = this;
List<AttributeType> attrList = new ArrayList<>(definition.attributeTypes.values());
if (extraAttrs != null) attrList.addAll(extraAttrs);
return Observable.fromIterable(attrList)
.flatMap(attr -> tokenscriptUtility.fetchAttrResult(token.getWallet(), attr, tokenId,
cAddr, definition, this, token.lastTxTime));
}
public Observable<TokenScriptResult.Attribute> resolveAttrs(Token token, List<BigInteger> tokenIds)
public Observable<TokenScriptResult.Attribute> resolveAttrs(Token token, List<BigInteger> tokenIds, List<AttributeType> extraAttrs)
{
TokenDefinition definition = getAssetDefinition(token.tokenInfo.chainId, token.tokenInfo.address);
//pre-fill tokenIds
@ -1425,7 +1434,7 @@ public class AssetDefinitionService implements ParseResult, AttributeInterface
//TODO: store transaction fetch time for multiple tokenIds
return resolveAttrs(token, tokenIds.get(0));
return resolveAttrs(token, tokenIds.get(0), extraAttrs);
}
private void resolveTokenIds(AttributeType attrType, List<BigInteger> tokenIds)

@ -160,11 +160,16 @@ public class FunctionActivity extends BaseActivity implements FunctionCallback,
e.printStackTrace();
}
viewModel.getAssetDefinitionService().resolveAttrs(token, tokenIds)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::onAttr, this::onError, () -> displayFunction(attrs.toString()))
.isDisposed();
// Fetch attributes local to this action and add them to the injected token properties
Map<String, TSAction> functions = viewModel.getAssetDefinitionService().getTokenFunctionMap(token.tokenInfo.chainId, token.getAddress());
TSAction action = functions.get(actionMethod);
List<AttributeType> localAttrs = (action != null && action.attributeTypes != null) ? new ArrayList<>(action.attributeTypes.values()) : null;
viewModel.getAssetDefinitionService().resolveAttrs(token, tokenIds, localAttrs)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::onAttr, this::onError, () -> displayFunction(attrs.toString()))
.isDisposed();
}
private void addMultipleTokenIds(StringBuilder sb)

@ -121,7 +121,7 @@ public class TokenscriptViewHolder extends BinderViewHolder<TicketRange> impleme
{
tokenId = data.tokenIds.get(0);
attrs = assetDefinitionService.getTokenAttrs(token, tokenId, data.tokenIds.size());
assetDefinitionService.resolveAttrs(token, tokenId)
assetDefinitionService.resolveAttrs(token, tokenId, null) // Can a view have local attributes?
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::onAttr, this::onError, () -> displayTicket(attrs.toString(), data))

@ -651,14 +651,13 @@ public abstract class TokenscriptFunction
{
if (definition != null && definition.attributeTypes.containsKey(arg.element.ref))
{
arg.element.value = fetchAttrResult(walletAddress, arg.element.ref, tokenId, null, definition, attrIf).blockingSingle().text;
arg.element.value = fetchAttrResult(walletAddress, definition.attributeTypes.get(arg.element.ref), tokenId, null, definition, attrIf).blockingSingle().text;
}
}
public Observable<TokenScriptResult.Attribute> fetchAttrResult(String walletAddress, String attribute, BigInteger tokenId, ContractAddress cAddr, TokenDefinition td, AttributeInterface attrIf)
public Observable<TokenScriptResult.Attribute> fetchAttrResult(String walletAddress, AttributeType attr, BigInteger tokenId, ContractAddress cAddr, TokenDefinition td, AttributeInterface attrIf)
{
AttributeType attr = td.attributeTypes.get(attribute);
if (attr == null) return Observable.fromCallable(() -> null);
if (attr.function == null) // static attribute from tokenId (eg city mapping from tokenId)
{
@ -692,7 +691,7 @@ public abstract class TokenscriptFunction
td.context.attrInterface = attrIf;
return Observable.fromIterable(new ArrayList<>(td.attributeTypes.values()))
.flatMap(attr -> fetchAttrResult(walletAddress, attr.id, tokenId, cAddr, td, attrIf));
.flatMap(attr -> fetchAttrResult(walletAddress, attr, tokenId, cAddr, td, attrIf));
}
private Observable<TokenScriptResult.Attribute> staticAttribute(AttributeType attr, BigInteger tokenId)

@ -652,14 +652,12 @@ public abstract class TokenscriptFunction
{
if (definition != null && definition.attributeTypes.containsKey(arg.element.ref))
{
arg.element.value = fetchAttrResult(walletAddress, arg.element.ref, tokenId, null, definition, attrIf).blockingSingle().text;
arg.element.value = fetchAttrResult(walletAddress, definition.attributeTypes.get(arg.element.ref), tokenId, null, definition, attrIf).blockingSingle().text;
}
}
public Observable<TokenScriptResult.Attribute> fetchAttrResult(String walletAddress, String attribute, BigInteger tokenId, ContractAddress cAddr, TokenDefinition td, AttributeInterface attrIf)
public Observable<TokenScriptResult.Attribute> fetchAttrResult(String walletAddress, AttributeType attr, BigInteger tokenId, ContractAddress cAddr, TokenDefinition td, AttributeInterface attrIf)
{
AttributeType attr = td.attributeTypes.get(attribute);
if (attr == null) return Observable.fromCallable(() -> null);
if (attr.function == null) // static attribute from tokenId (eg city mapping from tokenId)
{
@ -693,7 +691,7 @@ public abstract class TokenscriptFunction
td.context.attrInterface = attrIf;
return Observable.fromIterable(new ArrayList<>(td.attributeTypes.values()))
.flatMap(attr -> fetchAttrResult(walletAddress, attr.id, tokenId, cAddr, td, attrIf));
.flatMap(attr -> fetchAttrResult(walletAddress, attr, tokenId, cAddr, td, attrIf));
}
private Observable<TokenScriptResult.Attribute> staticAttribute(AttributeType attr, BigInteger tokenId)

Loading…
Cancel
Save