use new syntax on attributes

pull/1405/head
James Sangalli 4 years ago
parent c4810cc04e
commit 8d7ad202b9
  1. 42
      app/src/androidTest/java/com/alphawallet/app/entity/tokenscript/TokenscriptFunctionTest.java
  2. 25
      app/src/main/assets/xdaicanonicalized.xml
  3. 2
      app/src/main/java/com/alphawallet/app/entity/tokenscript/EventUtils.java
  4. 35
      app/src/main/java/com/alphawallet/app/entity/tokenscript/TokenscriptFunction.java
  5. 50
      app/src/main/java/com/alphawallet/app/service/AssetDefinitionService.java
  6. 14
      app/src/main/java/com/alphawallet/app/ui/FunctionActivity.java
  7. 7
      dmz/src/main/java/com/alphawallet/token/web/AppSiteController.java
  8. 17
      dmz/src/main/java/com/alphawallet/token/web/Ethereum/TokenscriptFunction.java
  9. 13
      lib/src/main/java/com/alphawallet/token/entity/Attribute.java
  10. 4
      lib/src/main/java/com/alphawallet/token/entity/AttributeInterface.java
  11. 2
      lib/src/main/java/com/alphawallet/token/entity/TSAction.java
  12. 2
      lib/src/main/java/com/alphawallet/token/entity/TSTokenViewHolder.java
  13. 2
      lib/src/main/java/com/alphawallet/token/entity/TransactionResult.java
  14. 35
      lib/src/main/java/com/alphawallet/token/tools/TokenDefinition.java
  15. 2
      lib/src/test/java/com/alphawallet/token/tools/TokenDefinitionTest.java
  16. 30
      lib/src/test/ts/entrytoken.canonicalized.xml
  17. 17
      util/src/main/java/com/alphawallet/scripttool/Entity/TokenscriptFunction.java
  18. 6
      util/src/main/java/com/alphawallet/scripttool/ScriptTool.java

@ -442,7 +442,8 @@ public class TokenscriptFunctionTest implements ParseResult {
" </ts:view>\n" + " </ts:view>\n" +
" </ts:card>\n" + " </ts:card>\n" +
" </ts:cards>\n" + " </ts:cards>\n" +
" <ts:attribute-type name=\"locality\" syntax=\"1.3.6.1.4.1.1466.115.121.1.15\">\n" + " <ts:attribute name=\"locality\">\n" +
" <ts:type><ts:syntax>1.3.6.1.4.1.1466.115.121.1.15</ts:syntax></ts:type>\n" +
" <ts:origins>\n" + " <ts:origins>\n" +
" <ethereum:call as=\"utf8\" contract=\"EntryToken\" function=\"getLocality\">\n" + " <ethereum:call as=\"utf8\" contract=\"EntryToken\" function=\"getLocality\">\n" +
" <ts:data>\n" + " <ts:data>\n" +
@ -451,8 +452,9 @@ public class TokenscriptFunctionTest implements ParseResult {
" </ethereum:call>\n" + " </ethereum:call>\n" +
" </ts:origins>\n" + " </ts:origins>\n" +
"\n" + "\n" +
" </ts:attribute-type>\n" + " </ts:attribute>\n" +
" <ts:attribute-type name=\"time\" syntax=\"1.3.6.1.4.1.1466.115.121.1.24\">\n" + " <ts:attribute name=\"time\">\n" +
" <ts:type><ts:syntax>1.3.6.1.4.1.1466.115.121.1.24</ts:syntax></ts:type>\n" +
" <ts:label>\n" + " <ts:label>\n" +
" <ts:string xml:lang=\"en\">Time</ts:string>\n" + " <ts:string xml:lang=\"en\">Time</ts:string>\n" +
" <ts:string xml:lang=\"zh\">时间</ts:string>\n" + " <ts:string xml:lang=\"zh\">时间</ts:string>\n" +
@ -460,8 +462,9 @@ public class TokenscriptFunctionTest implements ParseResult {
" <ts:origins>\n" + " <ts:origins>\n" +
" <ts:token-id as=\"utf8\" bitmask=\"0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000000000\"></ts:token-id>\n" + " <ts:token-id as=\"utf8\" bitmask=\"0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000000000\"></ts:token-id>\n" +
" </ts:origins>\n" + " </ts:origins>\n" +
" </ts:attribute-type>\n" + " </ts:attribute>\n" +
" <ts:attribute-type name=\"expired\" syntax=\"1.3.6.1.4.1.1466.115.121.1.7\"> <!-- boolean -->\n" + " <ts:attribute name=\"expired\"> <!-- boolean -->\n" +
" <ts:type><ts:syntax>1.3.6.1.4.1.1466.115.121.1.7</ts:syntax></ts:type>\n" +
" <ts:origins>\n" + " <ts:origins>\n" +
" <ethereum:call as=\"bool\" contract=\"EntryToken\" function=\"isExpired\">\n" + " <ethereum:call as=\"bool\" contract=\"EntryToken\" function=\"isExpired\">\n" +
" <ts:data>\n" + " <ts:data>\n" +
@ -469,8 +472,9 @@ public class TokenscriptFunctionTest implements ParseResult {
" </ts:data>\n" + " </ts:data>\n" +
" </ethereum:call>\n" + " </ethereum:call>\n" +
" </ts:origins>\n" + " </ts:origins>\n" +
" </ts:attribute-type>\n" + " </ts:attribute>\n" +
" <ts:attribute-type name=\"street\" syntax=\"1.3.6.1.4.1.1466.115.121.1.15\"> <!-- string -->\n" + " <ts:attribute name=\"street\"> <!-- string -->\n" +
" <ts:type><ts:syntax>1.3.6.1.4.1.1466.115.121.1.15</ts:syntax></ts:type>\n" +
" <ts:origins>\n" + " <ts:origins>\n" +
" <ethereum:call as=\"utf8\" contract=\"EntryToken\" function=\"getStreet\">\n" + " <ethereum:call as=\"utf8\" contract=\"EntryToken\" function=\"getStreet\">\n" +
" <ts:data>\n" + " <ts:data>\n" +
@ -478,8 +482,9 @@ public class TokenscriptFunctionTest implements ParseResult {
" </ts:data>\n" + " </ts:data>\n" +
" </ethereum:call>\n" + " </ethereum:call>\n" +
" </ts:origins>\n" + " </ts:origins>\n" +
" </ts:attribute-type>\n" + " </ts:attribute>\n" +
" <ts:attribute-type name=\"building\" syntax=\"1.3.6.1.4.1.1466.115.121.1.15\"> <!-- string -->\n" + " <ts:attribute name=\"building\"> <!-- string -->\n" +
" <ts:type><ts:syntax>1.3.6.1.4.1.1466.115.121.1.15</ts:syntax></ts:type>\n" +
" <ts:origins>\n" + " <ts:origins>\n" +
" <ethereum:call as=\"utf8\" contract=\"EntryToken\" function=\"getBuildingName\">\n" + " <ethereum:call as=\"utf8\" contract=\"EntryToken\" function=\"getBuildingName\">\n" +
" <ts:data>\n" + " <ts:data>\n" +
@ -487,8 +492,9 @@ public class TokenscriptFunctionTest implements ParseResult {
" </ts:data>\n" + " </ts:data>\n" +
" </ethereum:call>\n" + " </ethereum:call>\n" +
" </ts:origins>\n" + " </ts:origins>\n" +
" </ts:attribute-type>\n" + " </ts:attribute>\n" +
" <ts:attribute-type name=\"state\" syntax=\"1.3.6.1.4.1.1466.115.121.1.15\"> <!-- string -->\n" + " <ts:attribute name=\"state\"> <!-- string -->\n" +
" <ts:type><ts:syntax>1.3.6.1.4.1.1466.115.121.1.15</ts:syntax></ts:type>\n" +
" <ts:origins>\n" + " <ts:origins>\n" +
" <ethereum:call as=\"utf8\" contract=\"EntryToken\" function=\"getState\">\n" + " <ethereum:call as=\"utf8\" contract=\"EntryToken\" function=\"getState\">\n" +
" <ts:data>\n" + " <ts:data>\n" +
@ -496,7 +502,7 @@ public class TokenscriptFunctionTest implements ParseResult {
" </ts:data>\n" + " </ts:data>\n" +
" </ethereum:call>\n" + " </ethereum:call>\n" +
" </ts:origins>\n" + " </ts:origins>\n" +
" </ts:attribute-type>\n" + " </ts:attribute>\n" +
"</ts:token>\n"; "</ts:token>\n";
private TokenDefinition entryToken; private TokenDefinition entryToken;
@ -511,16 +517,16 @@ public class TokenscriptFunctionTest implements ParseResult {
@Test @Test
public void attributeTypesShouldExist() { public void attributeTypesShouldExist() {
assertTrue("should have a street attribute", entryToken.attributeTypes.containsKey("street")); assertTrue("should have a street attribute", entryToken.attributes.containsKey("street"));
assertTrue("should have a building attribute", entryToken.attributeTypes.containsKey("building")); assertTrue("should have a building attribute", entryToken.attributes.containsKey("building"));
assertTrue("should have a state attribute", entryToken.attributeTypes.containsKey("state")); assertTrue("should have a state attribute", entryToken.attributes.containsKey("state"));
} }
@Test @Test
public void attributeTypesShouldBeUTF8() { public void attributeTypesShouldBeUTF8() {
As streetType = entryToken.attributeTypes.get("street").as; As streetType = entryToken.attributes.get("street").as;
As buildingType = entryToken.attributeTypes.get("building").as; As buildingType = entryToken.attributes.get("building").as;
As stateType = entryToken.attributeTypes.get("state").as; As stateType = entryToken.attributes.get("state").as;
assertTrue("street, building & state should be a UTF8 origin", assertTrue("street, building & state should be a UTF8 origin",
streetType.equals(As.UTF8) && buildingType.equals(As.UTF8) && stateType.equals(As.UTF8)); streetType.equals(As.UTF8) && buildingType.equals(As.UTF8) && stateType.equals(As.UTF8));
} }

@ -1,9 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><ts:card xmlns:ts="http://tokenscript.org/2020/06/tokenscript" xmlns:asnx="urn:ietf:params:xml:ns:asnx" xmlns:ethereum="urn:ethereum:constantinople" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" type="action" xsi:schemaLocation="http://tokenscript.org/2020/06/tokenscript http://tokenscript.org/2020/03/tokenscript.xsd"> <?xml version="1.0" encoding="UTF-8" standalone="no"?><ts:card xmlns:ts="http://tokenscript.org/2020/06/tokenscript" xmlns:asnx="urn:ietf:params:xml:ns:asnx" xmlns:ethereum="urn:ethereum:constantinople" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" type="action" xsi:schemaLocation="http://tokenscript.org/2020/06/tokenscript http://tokenscript.org/2020/06/tokenscript.xsd">
<ts:label> <ts:label>
<ts:string xml:lang="en">Convert to DAI</ts:string> <ts:string xml:lang="en">Convert to DAI</ts:string>
<ts:string xml:lang="zh">將xDAI轉爲DAI</ts:string> <ts:string xml:lang="zh">將xDAI轉爲DAI</ts:string>
</ts:label> </ts:label>
<ts:attribute-type name="amount" syntax="1.3.6.1.4.1.1466.115.121.1.36"> <ts:attribute name="amount">
<ts:type><ts:syntax>1.3.6.1.4.1.1466.115.121.1.36</ts:syntax></ts:type>
<ts:label> <ts:label>
<ts:string xml:lang="en">Amount</ts:string> <ts:string xml:lang="en">Amount</ts:string>
<ts:string xml:lang="zh">代幣金額</ts:string> <ts:string xml:lang="zh">代幣金額</ts:string>
@ -13,7 +14,7 @@
rationale for hardcoding: avoiding over-design --> rationale for hardcoding: avoiding over-design -->
<ts:user-entry as="e18"/> <ts:user-entry as="e18"/>
</ts:origins> </ts:origins>
</ts:attribute-type> </ts:attribute>
<!-- because this action has xdai as input, it should be listed as <!-- because this action has xdai as input, it should be listed as
an action under XDAI's token view. --> an action under XDAI's token view. -->
<ts:input> <ts:input>
@ -49,10 +50,10 @@
exclude="low_balance" to the root element. exclude="low_balance" to the root element.
--> -->
<ts:transaction> <ts:transaction>
<ethereum:transfer> <ethereum:transaction>
<ethereum:to>0x7301CFA0e1756B71869E93d4e4Dca5c7d0eb0AA6</ethereum:to> <ethereum:to>0x7301CFA0e1756B71869E93d4e4Dca5c7d0eb0AA6</ethereum:to>
<ethereum:ether ref="amount"/> <ethereum:value ref="amount"/>
</ethereum:transfer> </ethereum:transaction>
</ts:transaction> </ts:transaction>
<ts:view xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <ts:view xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<style type="text/css">h3 { color: #111; font-family: 'Open Sans', sans-serif; font-size: 20px; font-weight: 300; line-height: 32px; } <style type="text/css">h3 { color: #111; font-family: 'Open Sans', sans-serif; font-size: 20px; font-weight: 300; line-height: 32px; }
@ -192,15 +193,15 @@
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms> </ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>wvq+ZMKlljAzgQYNAsCMatiDDicn4l1uj5yJKMhlfeE=</ds:DigestValue> <ds:DigestValue>7D1ZpnmqhQKkWZXSS9CtgDz3mV/jC6xCmCWxemvJEgc=</ds:DigestValue>
</ds:Reference> </ds:Reference>
</ds:SignedInfo> </ds:SignedInfo>
<ds:SignatureValue> <ds:SignatureValue>
gPFjTUGyZt1s1msP1eWvp+FsMa1a6a9zZNtNuSbZ/+yvObTz5WuN7kD+FuucpsoGUoA1UmYqU4IP exm01j3IHOuGykCvXRXVTJbu380BlQXoiEksyFB/CBpWcYpaY9aLc7fD7SMckWNYNVWaBRwEXDU2
4kfnzHroMdBn7Y8MR9mQqDon3xjE8uMbyHC7qtah9E2uwJmZlfhjdGwUxlAye1j+rHa74LNeH7ql Pmv6B3LwaOwco1fcibCFcEORd2IgnuJPrqd9jzpWArksbYrKZx0im9IrxyEtm+rISv423TsXS+u3
at0nCyUN8Z0YVLq3QQ1fcxPeKVC1ryKtkg6QJB+qd5ZavXdMaUOfwf/roWIo73emGkuHtC2zNN2K h6taeZp2yorOhcodF7+uzwmOQ4mt6NZ87HYhXyfF6GUl5kzg7TZyooTn8GJfZqjk6ZOXHQor3Z8E
40qoVyyPEZ4GM8GmQS8yltMWkfjK0+RCEfZO/ert4BK5xa7SVk7JJshVo9fYNa26alSxgHghmA6/ s1ijT42Diotw2qcEgCNZshTn28r70dY2NUExmjLs9u8vNV1OnIxRWDbCbK06rYue/6w0AOGm8d2O
qHXlVf0WMf4qkXk5iu3XV+xlY/32JdVRvYjunA== /eWhBLoKKgdx5esKzLyPE2edX1rpYNCiweUQaQ==
</ds:SignatureValue> </ds:SignatureValue>
<ds:KeyInfo> <ds:KeyInfo>
<ds:KeyName>AlphaWallet</ds:KeyName> <ds:KeyName>AlphaWallet</ds:KeyName>

@ -260,7 +260,7 @@ public abstract class EventUtils
String selectVal; String selectVal;
// Note this param gets interpreted according to the script 'syntax' // Note this param gets interpreted according to the script 'syntax'
// by the attribute value conversion function getSyntaxVal(String ...) in class AttributeType // by the attribute value conversion function getSyntaxVal(String ...) in class Attribute
switch (typeName.toLowerCase()) switch (typeName.toLowerCase())
{ {
case "string": case "string":

@ -12,8 +12,8 @@ import com.alphawallet.app.web3j.FunctionReturnDecoder;
import com.alphawallet.app.web3j.TypeReference; import com.alphawallet.app.web3j.TypeReference;
import com.alphawallet.app.web3j.datatypes.Function; import com.alphawallet.app.web3j.datatypes.Function;
import com.alphawallet.token.entity.As; import com.alphawallet.token.entity.As;
import com.alphawallet.token.entity.Attribute;
import com.alphawallet.token.entity.AttributeInterface; import com.alphawallet.token.entity.AttributeInterface;
import com.alphawallet.token.entity.AttributeType;
import com.alphawallet.token.entity.ContractAddress; import com.alphawallet.token.entity.ContractAddress;
import com.alphawallet.token.entity.FunctionDefinition; import com.alphawallet.token.entity.FunctionDefinition;
import com.alphawallet.token.entity.MethodArg; import com.alphawallet.token.entity.MethodArg;
@ -55,7 +55,7 @@ public abstract class TokenscriptFunction
{ {
public static final String TOKENSCRIPT_CONVERSION_ERROR = "<error>"; public static final String TOKENSCRIPT_CONVERSION_ERROR = "<error>";
private final Map<String, AttributeType> localAttrs = new ConcurrentHashMap<>(); private final Map<String, Attribute> localAttrs = new ConcurrentHashMap<>();
private final Map<String, String> refTags = new ConcurrentHashMap<>(); private final Map<String, String> refTags = new ConcurrentHashMap<>();
public Function generateTransactionFunction(Token token, BigInteger tokenId, TokenDefinition definition, FunctionDefinition function, AttributeInterface attrIf) public Function generateTransactionFunction(Token token, BigInteger tokenId, TokenDefinition definition, FunctionDefinition function, AttributeInterface attrIf)
@ -499,7 +499,7 @@ public abstract class TokenscriptFunction
return argBytes; return argBytes;
} }
private String handleTransactionResult(TransactionResult result, Function function, String responseValue, AttributeType attr, long lastTransactionTime) private String handleTransactionResult(TransactionResult result, Function function, String responseValue, Attribute attr, long lastTransactionTime)
{ {
String transResult = null; String transResult = null;
try try
@ -606,7 +606,7 @@ public abstract class TokenscriptFunction
return name; return name;
} }
public TokenScriptResult.Attribute parseFunctionResult(TransactionResult transactionResult, AttributeType attr) public TokenScriptResult.Attribute parseFunctionResult(TransactionResult transactionResult, Attribute attr)
{ {
String res = attr.getSyntaxVal(transactionResult.result); String res = attr.getSyntaxVal(transactionResult.result);
BigInteger val = transactionResult.tokenId; //? BigInteger val = transactionResult.tokenId; //?
@ -648,7 +648,7 @@ public abstract class TokenscriptFunction
* @param definition * @param definition
* @return * @return
*/ */
public Observable<TransactionResult> fetchResultFromEthereum(Token token, ContractAddress override, AttributeType attr, public Observable<TransactionResult> fetchResultFromEthereum(Token token, ContractAddress override, Attribute attr,
BigInteger tokenId, TokenDefinition definition, AttributeInterface attrIf, long lastTransactionTime) BigInteger tokenId, TokenDefinition definition, AttributeInterface attrIf, long lastTransactionTime)
{ {
return Observable.fromCallable(() -> { return Observable.fromCallable(() -> {
@ -720,19 +720,19 @@ public abstract class TokenscriptFunction
{ {
return attrRes.text; return attrRes.text;
} }
else if (definition != null && definition.attributeTypes.containsKey(element.ref)) //resolve from attribute else if (definition != null && definition.attributes.containsKey(element.ref)) //resolve from attribute
{ {
AttributeType attr = definition.attributeTypes.get(element.ref); Attribute attr = definition.attributes.get(element.ref);
return fetchArgValue(token, element, attr, tokenId, definition, attrIf); return fetchArgValue(token, element, attr, tokenId, definition, attrIf);
} }
else if (localAttrs.containsKey(element.ref)) //wasn't able to resolve, attempt to resolve from local attributes or mark null if unresolved user input else if (localAttrs.containsKey(element.ref)) //wasn't able to resolve, attempt to resolve from local attributes or mark null if unresolved user input
{ {
AttributeType attr = localAttrs.get(element.ref); Attribute attr = localAttrs.get(element.ref);
return fetchArgValue(token, element, attr, tokenId, definition, attrIf); return fetchArgValue(token, element, attr, tokenId, definition, attrIf);
} }
else if (localAttrs.containsKey(element.localRef)) else if (localAttrs.containsKey(element.localRef))
{ {
AttributeType attr = localAttrs.get(element.localRef); Attribute attr = localAttrs.get(element.localRef);
return fetchArgValue(token, element, attr, tokenId, definition, attrIf); return fetchArgValue(token, element, attr, tokenId, definition, attrIf);
} }
else if (!TextUtils.isEmpty(element.localRef) && refTags.containsKey(element.localRef)) else if (!TextUtils.isEmpty(element.localRef) && refTags.containsKey(element.localRef))
@ -745,7 +745,7 @@ public abstract class TokenscriptFunction
} }
} }
private String fetchArgValue(Token token, TokenscriptElement element, AttributeType attr, BigInteger tokenId, TokenDefinition definition, AttributeInterface attrIf) private String fetchArgValue(Token token, TokenscriptElement element, Attribute attr, BigInteger tokenId, TokenDefinition definition, AttributeInterface attrIf)
{ {
if (attr.userInput) if (attr.userInput)
{ {
@ -785,7 +785,8 @@ public abstract class TokenscriptFunction
* @param attrIf * @param attrIf
* @return * @return
*/ */
public Observable<TokenScriptResult.Attribute> fetchAttrResult(Token token, AttributeType attr, BigInteger tokenId, ContractAddress cAddr,
public Observable<TokenScriptResult.Attribute> fetchAttrResult(Token token, Attribute attr, BigInteger tokenId, ContractAddress cAddr,
TokenDefinition td, AttributeInterface attrIf, boolean itemView) TokenDefinition td, AttributeInterface attrIf, boolean itemView)
{ {
if (attr == null) if (attr == null)
@ -831,7 +832,7 @@ public abstract class TokenscriptFunction
} }
} }
private Observable<TokenScriptResult.Attribute> staticAttribute(AttributeType attr, BigInteger tokenId) private Observable<TokenScriptResult.Attribute> staticAttribute(Attribute attr, BigInteger tokenId)
{ {
return Observable.fromCallable(() -> { return Observable.fromCallable(() -> {
try try
@ -854,7 +855,7 @@ public abstract class TokenscriptFunction
}); });
} }
private Observable<TokenScriptResult.Attribute> resultFromDatabase(TransactionResult transactionResult, AttributeType attr) private Observable<TokenScriptResult.Attribute> resultFromDatabase(TransactionResult transactionResult, Attribute attr)
{ {
return Observable.fromCallable(() -> parseFunctionResult(transactionResult, attr)); return Observable.fromCallable(() -> parseFunctionResult(transactionResult, attr));
} }
@ -876,7 +877,7 @@ public abstract class TokenscriptFunction
return result; return result;
} }
public String convertInputValue(AttributeType attr, String valueFromInput) public String convertInputValue(Attribute attr, String valueFromInput)
{ {
String convertedValue = ""; String convertedValue = "";
try try
@ -953,10 +954,10 @@ public abstract class TokenscriptFunction
return convertedValue; return convertedValue;
} }
public void buildAttrMap(List<AttributeType> attrs) public void buildAttrMap(List<Attribute> attrs)
{ {
localAttrs.clear(); localAttrs.clear();
for (AttributeType attr : attrs) for (Attribute attr : attrs)
{ {
localAttrs.put(attr.name, attr); localAttrs.put(attr.name, attr);
} }
@ -971,7 +972,7 @@ public abstract class TokenscriptFunction
return attrResult; return attrResult;
} }
private TransactionResult addParseResultIfValid(Token token, BigInteger tokenId, AttributeType attr, TransactionResult result) private TransactionResult addParseResultIfValid(Token token, BigInteger tokenId, Attribute attr, TransactionResult result)
{ {
if (!TextUtils.isEmpty(result.result)) if (!TextUtils.isEmpty(result.result))
{ {

@ -41,8 +41,8 @@ import com.alphawallet.app.util.Utils;
import com.alphawallet.app.viewmodel.HomeViewModel; import com.alphawallet.app.viewmodel.HomeViewModel;
import com.alphawallet.app.web3j.FunctionEncoder; import com.alphawallet.app.web3j.FunctionEncoder;
import com.alphawallet.app.web3j.datatypes.Function; import com.alphawallet.app.web3j.datatypes.Function;
import com.alphawallet.token.entity.Attribute;
import com.alphawallet.token.entity.AttributeInterface; import com.alphawallet.token.entity.AttributeInterface;
import com.alphawallet.token.entity.AttributeType;
import com.alphawallet.token.entity.ContractAddress; import com.alphawallet.token.entity.ContractAddress;
import com.alphawallet.token.entity.ContractInfo; import com.alphawallet.token.entity.ContractInfo;
import com.alphawallet.token.entity.EvaluateSelection; import com.alphawallet.token.entity.EvaluateSelection;
@ -325,7 +325,7 @@ public class AssetDefinitionService implements ParseResult, AttributeInterface
} }
@Override @Override
public boolean resolveOptimisedAttr(ContractAddress contract, AttributeType attr, TransactionResult transactionResult) public boolean resolveOptimisedAttr(ContractAddress contract, Attribute attr, TransactionResult transactionResult)
{ {
boolean optimised = false; boolean optimised = false;
if (attr.function == null) return false; if (attr.function == null) return false;
@ -372,9 +372,9 @@ public class AssetDefinitionService implements ParseResult, AttributeInterface
tokenscriptUtility.addLocalRefs(refs); tokenscriptUtility.addLocalRefs(refs);
} }
private AttributeType getTypeFromList(String key, List<AttributeType> attrList) private Attribute getTypeFromList(String key, List<Attribute> attrList)
{ {
for (AttributeType attr : attrList) for (Attribute attr : attrList)
{ {
if (attr.name.equals(key)) return attr; if (attr.name.equals(key)) return attr;
} }
@ -395,7 +395,7 @@ public class AssetDefinitionService implements ParseResult, AttributeInterface
TokenDefinition definition = getAssetDefinition(token.tokenInfo.chainId, token.tokenInfo.address); TokenDefinition definition = getAssetDefinition(token.tokenInfo.chainId, token.tokenInfo.address);
if (definition != null) if (definition != null)
{ {
for (String key : definition.attributeTypes.keySet()) for (String key : definition.attributes.keySet())
{ {
result.setAttribute(key, getTokenscriptAttr(definition, token, tokenId, key)); result.setAttribute(key, getTokenscriptAttr(definition, token, tokenId, key));
} }
@ -407,7 +407,7 @@ public class AssetDefinitionService implements ParseResult, AttributeInterface
private TokenScriptResult.Attribute getTokenscriptAttr(TokenDefinition td, Token token, BigInteger tokenId, String attribute) private TokenScriptResult.Attribute getTokenscriptAttr(TokenDefinition td, Token token, BigInteger tokenId, String attribute)
{ {
TokenScriptResult.Attribute result = null; TokenScriptResult.Attribute result = null;
AttributeType attrtype = td.attributeTypes.get(attribute); Attribute attrtype = td.attributes.get(attribute);
try try
{ {
if (attrtype == null) if (attrtype == null)
@ -441,7 +441,7 @@ public class AssetDefinitionService implements ParseResult, AttributeInterface
public TokenScriptResult.Attribute getAttribute(Token token, BigInteger tokenId, String attribute) public TokenScriptResult.Attribute getAttribute(Token token, BigInteger tokenId, String attribute)
{ {
TokenDefinition definition = getAssetDefinition(token.tokenInfo.chainId, token.tokenInfo.address); TokenDefinition definition = getAssetDefinition(token.tokenInfo.chainId, token.tokenInfo.address);
if (definition != null && definition.attributeTypes.containsKey(attribute)) if (definition != null && definition.attributes.containsKey(attribute))
{ {
return getTokenscriptAttr(definition, token, tokenId, attribute); return getTokenscriptAttr(definition, token, tokenId, attribute);
} }
@ -968,9 +968,9 @@ public class AssetDefinitionService implements ParseResult, AttributeInterface
private void addToEventList(TokenDefinition tokenDef, ContractInfo cInfo) private void addToEventList(TokenDefinition tokenDef, ContractInfo cInfo)
{ {
for (String attrName : tokenDef.attributeTypes.keySet()) for (String attrName : tokenDef.attributes.keySet())
{ {
AttributeType attr = tokenDef.attributeTypes.get(attrName); Attribute attr = tokenDef.attributes.get(attrName);
if (attr.event != null) if (attr.event != null)
{ {
attr.event.originContract = cInfo; attr.event.originContract = cInfo;
@ -1062,7 +1062,7 @@ public class AssetDefinitionService implements ParseResult, AttributeInterface
Web3j web3j = getWeb3jService(originToken.tokenInfo.chainId); Web3j web3j = getWeb3jService(originToken.tokenInfo.chainId);
TokenDefinition td = getAssetDefinition(originToken.tokenInfo.chainId, originToken.getAddress()); TokenDefinition td = getAssetDefinition(originToken.tokenInfo.chainId, originToken.getAddress());
AttributeType attrType = td.attributeTypes.get(ev.attributeId); Attribute attrType = td.attributes.get(ev.attributeId);
for (EthLog.LogResult ethLog : logs) for (EthLog.LogResult ethLog : logs)
{ {
@ -1075,7 +1075,7 @@ public class AssetDefinitionService implements ParseResult, AttributeInterface
} }
} }
private void storeEventValue(EventDefinition ev, EthLog.LogResult log, AttributeType attr, private void storeEventValue(EventDefinition ev, EthLog.LogResult log, Attribute attr,
Token originToken, long blockTime, String selectVal) Token originToken, long blockTime, String selectVal)
{ {
//store result //store result
@ -1394,13 +1394,13 @@ public class AssetDefinitionService implements ParseResult, AttributeInterface
return styleData; return styleData;
} }
public List<AttributeType> getTokenViewLocalAttributes(int chainId, String contractAddr) public List<Attribute> getTokenViewLocalAttributes(int chainId, String contractAddr)
{ {
TokenDefinition td = getAssetDefinition(chainId, contractAddr); TokenDefinition td = getAssetDefinition(chainId, contractAddr);
List<AttributeType> results = new ArrayList<>(); List<Attribute> results = new ArrayList<>();
if (td != null) if (td != null)
{ {
Map<String, AttributeType> attrMap = td.getTokenViewLocalAttributes(); Map<String, Attribute> attrMap = td.getTokenViewLocalAttributes();
results.addAll(attrMap.values()); results.addAll(attrMap.values());
} }
@ -1660,8 +1660,8 @@ public class AssetDefinitionService implements ParseResult, AttributeInterface
TokenDefinition td = getDefinition(token.tokenInfo.chainId, token.tokenInfo.address); TokenDefinition td = getDefinition(token.tokenInfo.chainId, token.tokenInfo.address);
if (td == null) return token; if (td == null) return token;
List<AttributeType> attrs = new ArrayList<>(td.attributeTypes.values()); List<Attribute> attrs = new ArrayList<>(td.attributes.values());
for (AttributeType attr : attrs) for (Attribute attr : attrs)
{ {
if (attr.function == null) continue; if (attr.function == null) continue;
FunctionDefinition fd = attr.function; FunctionDefinition fd = attr.function;
@ -1680,7 +1680,7 @@ public class AssetDefinitionService implements ParseResult, AttributeInterface
Observable.fromIterable(token.getNonZeroArrayBalance()) Observable.fromIterable(token.getNonZeroArrayBalance())
.map(tokenId -> getFunctionResult(cAddr, attr, tokenId)) .map(tokenId -> getFunctionResult(cAddr, attr, tokenId))
.filter(txResult -> txResult.needsUpdating(token.lastTxTime)) .filter(txResult -> txResult.needsUpdating(token.lastTxTime))
.concatMap(result -> tokenscriptUtility.fetchAttrResult(token, td.attributeTypes.get(attr.name), result.tokenId, cAddr, td, this, false)) .concatMap(result -> tokenscriptUtility.fetchAttrResult(token, td.attributes.get(attr.name), result.tokenId, cAddr, td, this, false))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(); .subscribe();
@ -1691,7 +1691,7 @@ public class AssetDefinitionService implements ParseResult, AttributeInterface
TransactionResult tr = getFunctionResult(cAddr, attr, BigInteger.ZERO); TransactionResult tr = getFunctionResult(cAddr, attr, BigInteger.ZERO);
if (tr.needsUpdating(token.lastTxTime)) if (tr.needsUpdating(token.lastTxTime))
{ {
tokenscriptUtility.fetchAttrResult(token, td.attributeTypes.get(attr.name), tr.tokenId, cAddr, td, this, false) tokenscriptUtility.fetchAttrResult(token, td.attributes.get(attr.name), tr.tokenId, cAddr, td, this, false)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(); .subscribe();
@ -1771,7 +1771,7 @@ public class AssetDefinitionService implements ParseResult, AttributeInterface
} }
@Override @Override
public TransactionResult getFunctionResult(ContractAddress contract, AttributeType attr, BigInteger tokenId) public TransactionResult getFunctionResult(ContractAddress contract, Attribute attr, BigInteger tokenId)
{ {
TransactionResult tr = new TransactionResult(contract.chainId, contract.address, tokenId, attr); TransactionResult tr = new TransactionResult(contract.chainId, contract.address, tokenId, attr);
String dataBaseKey = functionKey(contract, tokenId, attr.name); String dataBaseKey = functionKey(contract, tokenId, attr.name);
@ -2015,7 +2015,7 @@ public class AssetDefinitionService implements ParseResult, AttributeInterface
tokenscriptUtility.clearParseMaps(); tokenscriptUtility.clearParseMaps();
} }
public Observable<TokenScriptResult.Attribute> resolveAttrs(Token token, BigInteger tokenId, List<AttributeType> extraAttrs, boolean itemView) public Observable<TokenScriptResult.Attribute> resolveAttrs(Token token, BigInteger tokenId, List<Attribute> extraAttrs, boolean itemView)
{ {
TokenDefinition definition = getAssetDefinition(token.tokenInfo.chainId, token.tokenInfo.address); TokenDefinition definition = getAssetDefinition(token.tokenInfo.chainId, token.tokenInfo.address);
ContractAddress cAddr = new ContractAddress(token.tokenInfo.chainId, token.tokenInfo.address); ContractAddress cAddr = new ContractAddress(token.tokenInfo.chainId, token.tokenInfo.address);
@ -2025,7 +2025,7 @@ public class AssetDefinitionService implements ParseResult, AttributeInterface
definition.context.cAddr = cAddr; definition.context.cAddr = cAddr;
definition.context.attrInterface = this; definition.context.attrInterface = this;
List<AttributeType> attrList = new ArrayList<>(definition.attributeTypes.values()); List<Attribute> attrList = new ArrayList<>(definition.attributes.values());
if (extraAttrs != null) attrList.addAll(extraAttrs); if (extraAttrs != null) attrList.addAll(extraAttrs);
tokenscriptUtility.buildAttrMap(attrList); tokenscriptUtility.buildAttrMap(attrList);
@ -2035,11 +2035,11 @@ public class AssetDefinitionService implements ParseResult, AttributeInterface
cAddr, definition, this, itemView)); cAddr, definition, this, itemView));
} }
public Observable<TokenScriptResult.Attribute> resolveAttrs(Token token, List<BigInteger> tokenIds, List<AttributeType> extraAttrs) public Observable<TokenScriptResult.Attribute> resolveAttrs(Token token, List<BigInteger> tokenIds, List<Attribute> extraAttrs)
{ {
TokenDefinition definition = getAssetDefinition(token.tokenInfo.chainId, token.tokenInfo.address); TokenDefinition definition = getAssetDefinition(token.tokenInfo.chainId, token.tokenInfo.address);
//pre-fill tokenIds //pre-fill tokenIds
for (AttributeType attrType : definition.attributeTypes.values()) for (Attribute attrType : definition.attributes.values())
{ {
resolveTokenIds(attrType, tokenIds); resolveTokenIds(attrType, tokenIds);
} }
@ -2049,7 +2049,7 @@ public class AssetDefinitionService implements ParseResult, AttributeInterface
return resolveAttrs(token, tokenIds.get(0), extraAttrs, false); return resolveAttrs(token, tokenIds.get(0), extraAttrs, false);
} }
private void resolveTokenIds(AttributeType attrType, List<BigInteger> tokenIds) private void resolveTokenIds(Attribute attrType, List<BigInteger> tokenIds)
{ {
if (attrType.function == null) return; if (attrType.function == null) return;
@ -2156,7 +2156,7 @@ public class AssetDefinitionService implements ParseResult, AttributeInterface
return cr; return cr;
} }
public String convertInputValue(AttributeType attr, String valueFromInput) public String convertInputValue(Attribute attr, String valueFromInput)
{ {
return tokenscriptUtility.convertInputValue(attr, valueFromInput); return tokenscriptUtility.convertInputValue(attr, valueFromInput);
} }

@ -41,7 +41,7 @@ import com.alphawallet.app.widget.FunctionButtonBar;
import com.alphawallet.app.widget.SignMessageDialog; import com.alphawallet.app.widget.SignMessageDialog;
import com.alphawallet.app.widget.SignTransactionDialog; import com.alphawallet.app.widget.SignTransactionDialog;
import com.alphawallet.app.widget.SystemView; import com.alphawallet.app.widget.SystemView;
import com.alphawallet.token.entity.AttributeType; import com.alphawallet.token.entity.Attribute;
import com.alphawallet.token.entity.MethodArg; import com.alphawallet.token.entity.MethodArg;
import com.alphawallet.token.entity.TSAction; import com.alphawallet.token.entity.TSAction;
import com.alphawallet.token.entity.TokenScriptResult; import com.alphawallet.token.entity.TokenScriptResult;
@ -169,7 +169,7 @@ public class FunctionActivity extends BaseActivity implements FunctionCallback,
// Fetch attributes local to this action and add them to the injected token properties // 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()); Map<String, TSAction> functions = viewModel.getAssetDefinitionService().getTokenFunctionMap(token.tokenInfo.chainId, token.getAddress());
TSAction action = functions.get(actionMethod); TSAction action = functions.get(actionMethod);
List<AttributeType> localAttrs = (action != null && action.attributeTypes != null) ? new ArrayList<>(action.attributeTypes.values()) : null; List<Attribute> localAttrs = (action != null && action.attributeTypes != null) ? new ArrayList<>(action.attributeTypes.values()) : null;
viewModel.getAssetDefinitionService().resolveAttrs(token, tokenIds, localAttrs) viewModel.getAssetDefinitionService().resolveAttrs(token, tokenIds, localAttrs)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
@ -288,7 +288,7 @@ public class FunctionActivity extends BaseActivity implements FunctionCallback,
CalcJsValueCallback cb = new CalcJsValueCallback() CalcJsValueCallback cb = new CalcJsValueCallback()
{ {
@Override @Override
public void calculationCompleted(String value, String result, TokenscriptElement e, AttributeType attr) public void calculationCompleted(String value, String result, TokenscriptElement e, Attribute attr)
{ {
if (BuildConfig.DEBUG) System.out.println("ATTR/FA: Resolve " + value + " : " + result); if (BuildConfig.DEBUG) System.out.println("ATTR/FA: Resolve " + value + " : " + result);
//need to find attr //need to find attr
@ -338,7 +338,7 @@ public class FunctionActivity extends BaseActivity implements FunctionCallback,
{ {
if (e.ref != null && e.ref.length() > 0 && action.attributeTypes != null) if (e.ref != null && e.ref.length() > 0 && action.attributeTypes != null)
{ {
AttributeType attr = action.attributeTypes.get(e.ref); Attribute attr = action.attributeTypes.get(e.ref);
if (attr != null && attr.userInput) if (attr != null && attr.userInput)
{ {
resolveInputCheckCount++; resolveInputCheckCount++;
@ -745,11 +745,11 @@ public class FunctionActivity extends BaseActivity implements FunctionCallback,
*/ */
private interface CalcJsValueCallback private interface CalcJsValueCallback
{ {
void calculationCompleted(String value, String result, TokenscriptElement e, AttributeType attr); void calculationCompleted(String value, String result, TokenscriptElement e, Attribute attr);
void unresolvedSymbolError(String value); void unresolvedSymbolError(String value);
} }
private void evaluateJavaScript(CalcJsValueCallback callback, String value, TokenscriptElement e, AttributeType attr) private void evaluateJavaScript(CalcJsValueCallback callback, String value, TokenscriptElement e, Attribute attr)
{ {
tokenView.evaluateJavascript( tokenView.evaluateJavascript(
"(function() { var x = document.getElementById(\"" + value + "\");\n" + "(function() { var x = document.getElementById(\"" + value + "\");\n" +
@ -768,7 +768,7 @@ public class FunctionActivity extends BaseActivity implements FunctionCallback,
}); });
} }
private void getValueFromInnerHTML(CalcJsValueCallback callback, String value, TokenscriptElement e, AttributeType attr) private void getValueFromInnerHTML(CalcJsValueCallback callback, String value, TokenscriptElement e, Attribute attr)
{ {
tokenView.evaluateJavascript( tokenView.evaluateJavascript(
"(function() { var x = document.getElementById(\"" + value + "\");\n" + "(function() { var x = document.getElementById(\"" + value + "\");\n" +

@ -1,5 +1,6 @@
package com.alphawallet.token.web; package com.alphawallet.token.web;
import com.alphawallet.token.entity.Attribute;
import com.github.cliftonlabs.json_simple.JsonObject; import com.github.cliftonlabs.json_simple.JsonObject;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
@ -46,7 +47,6 @@ import java.util.stream.Stream;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import com.alphawallet.token.entity.AttributeInterface; import com.alphawallet.token.entity.AttributeInterface;
import com.alphawallet.token.entity.AttributeType;
import com.alphawallet.token.entity.ContractAddress; import com.alphawallet.token.entity.ContractAddress;
import com.alphawallet.token.entity.ContractInfo; import com.alphawallet.token.entity.ContractInfo;
import com.alphawallet.token.entity.MagicLinkData; import com.alphawallet.token.entity.MagicLinkData;
@ -64,7 +64,6 @@ import com.alphawallet.token.web.Ethereum.TransactionHandler;
import com.alphawallet.token.web.Service.CryptoFunctions; import com.alphawallet.token.web.Service.CryptoFunctions;
import static com.alphawallet.token.tools.Convert.getEthString; import static com.alphawallet.token.tools.Convert.getEthString;
import static com.alphawallet.token.tools.ParseMagicLink.normal; import static com.alphawallet.token.tools.ParseMagicLink.normal;
import static com.alphawallet.token.tools.ParseMagicLink.spawnable;
import static com.alphawallet.token.web.Ethereum.TokenscriptFunction.ZERO_ADDRESS; import static com.alphawallet.token.web.Ethereum.TokenscriptFunction.ZERO_ADDRESS;
@Controller @Controller
@ -466,7 +465,7 @@ public class AppSiteController implements AttributeInterface
// once events are available we can selectively update entries. // once events are available we can selectively update entries.
@Override @Override
public TransactionResult getFunctionResult(ContractAddress contract, AttributeType attr, BigInteger tokenId) public TransactionResult getFunctionResult(ContractAddress contract, Attribute attr, BigInteger tokenId)
{ {
String addressFunctionKey = contract.address + "-" + attr.name; String addressFunctionKey = contract.address + "-" + attr.name;
TransactionResult tr = new TransactionResult(contract.chainId, contract.address, tokenId, attr); TransactionResult tr = new TransactionResult(contract.chainId, contract.address, tokenId, attr);
@ -499,7 +498,7 @@ public class AppSiteController implements AttributeInterface
//Not relevant for website - this function is to access wallet internal balance for tokens //Not relevant for website - this function is to access wallet internal balance for tokens
@Override @Override
public boolean resolveOptimisedAttr(ContractAddress contract, AttributeType attr, TransactionResult transactionResult) public boolean resolveOptimisedAttr(ContractAddress contract, Attribute attr, TransactionResult transactionResult)
{ {
return false; return false;
} }

@ -10,7 +10,6 @@ import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.FunctionReturnDecoder; import org.web3j.abi.FunctionReturnDecoder;
import org.web3j.abi.TypeReference; import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Address; import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.BytesType;
import org.web3j.abi.datatypes.Function; import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Int; import org.web3j.abi.datatypes.Int;
import org.web3j.abi.datatypes.Type; import org.web3j.abi.datatypes.Type;
@ -556,7 +555,7 @@ public abstract class TokenscriptFunction
return name; return name;
} }
public TokenScriptResult.Attribute parseFunctionResult(TransactionResult transactionResult, AttributeType attr) public TokenScriptResult.Attribute parseFunctionResult(TransactionResult transactionResult, Attribute attr)
{ {
String res = attr.getSyntaxVal(transactionResult.result); String res = attr.getSyntaxVal(transactionResult.result);
BigInteger val = transactionResult.tokenId; //? BigInteger val = transactionResult.tokenId; //?
@ -586,7 +585,7 @@ public abstract class TokenscriptFunction
* @param definition * @param definition
* @return * @return
*/ */
public Observable<TransactionResult> fetchResultFromEthereum(String walletAddress, ContractAddress override, AttributeType attr, BigInteger tokenId, TokenDefinition definition, AttributeInterface attrIf) public Observable<TransactionResult> fetchResultFromEthereum(String walletAddress, ContractAddress override, Attribute attr, BigInteger tokenId, TokenDefinition definition, AttributeInterface attrIf)
{ {
return Observable.fromCallable(() -> { return Observable.fromCallable(() -> {
ContractAddress useAddress; ContractAddress useAddress;
@ -649,14 +648,14 @@ public abstract class TokenscriptFunction
private void resolveReference(String walletAddress, MethodArg arg, BigInteger tokenId, TokenDefinition definition, AttributeInterface attrIf) private void resolveReference(String walletAddress, MethodArg arg, BigInteger tokenId, TokenDefinition definition, AttributeInterface attrIf)
{ {
if (definition != null && definition.attributeTypes.containsKey(arg.element.ref)) if (definition != null && definition.attributes.containsKey(arg.element.ref))
{ {
arg.element.value = fetchAttrResult(walletAddress, definition.attributeTypes.get(arg.element.ref), tokenId, null, definition, attrIf).blockingSingle().text; arg.element.value = fetchAttrResult(walletAddress, definition.attributes.get(arg.element.ref), tokenId, null, definition, attrIf).blockingSingle().text;
} }
} }
public Observable<TokenScriptResult.Attribute> fetchAttrResult(String walletAddress, AttributeType attr, BigInteger tokenId, ContractAddress cAddr, TokenDefinition td, AttributeInterface attrIf) public Observable<TokenScriptResult.Attribute> fetchAttrResult(String walletAddress, Attribute attr, BigInteger tokenId, ContractAddress cAddr, TokenDefinition td, AttributeInterface attrIf)
{ {
if (attr == null) return Observable.fromCallable(() -> null); if (attr == null) return Observable.fromCallable(() -> null);
if (attr.function == null) // static attribute from tokenId (eg city mapping from tokenId) if (attr.function == null) // static attribute from tokenId (eg city mapping from tokenId)
@ -690,11 +689,11 @@ public abstract class TokenscriptFunction
td.context.cAddr = cAddr; td.context.cAddr = cAddr;
td.context.attrInterface = attrIf; td.context.attrInterface = attrIf;
return Observable.fromIterable(new ArrayList<>(td.attributeTypes.values())) return Observable.fromIterable(new ArrayList<>(td.attributes.values()))
.flatMap(attr -> fetchAttrResult(walletAddress, attr, tokenId, cAddr, td, attrIf)); .flatMap(attr -> fetchAttrResult(walletAddress, attr, tokenId, cAddr, td, attrIf));
} }
private Observable<TokenScriptResult.Attribute> staticAttribute(AttributeType attr, BigInteger tokenId) private Observable<TokenScriptResult.Attribute> staticAttribute(Attribute attr, BigInteger tokenId)
{ {
return Observable.fromCallable(() -> { return Observable.fromCallable(() -> {
try try
@ -709,7 +708,7 @@ public abstract class TokenscriptFunction
}); });
} }
private Observable<TokenScriptResult.Attribute> resultFromDatabase(TransactionResult transactionResult, AttributeType attr) private Observable<TokenScriptResult.Attribute> resultFromDatabase(TransactionResult transactionResult, Attribute attr)
{ {
return Observable.fromCallable(() -> parseFunctionResult(transactionResult, attr)); return Observable.fromCallable(() -> parseFunctionResult(transactionResult, attr));
} }

@ -25,7 +25,7 @@ import static org.w3c.dom.Node.ELEMENT_NODE;
* Stormbird in Sydney * Stormbird in Sydney
*/ */
public class AttributeType { public class Attribute {
private static final int ADDRESS_SIZE = 160; private static final int ADDRESS_SIZE = 160;
private static final int ADDRESS_LENGTH_IN_HEX = ADDRESS_SIZE >> 2; private static final int ADDRESS_LENGTH_IN_HEX = ADDRESS_SIZE >> 2;
private static final int ADDRESS_LENGTH_IN_BYTES = ADDRESS_SIZE >> 3; private static final int ADDRESS_LENGTH_IN_BYTES = ADDRESS_SIZE >> 3;
@ -43,14 +43,21 @@ public class AttributeType {
public EventDefinition event = null; public EventDefinition event = null;
public boolean userInput = false; public boolean userInput = false;
public AttributeType(Element attr, TokenDefinition def) public Attribute(Element attr, TokenDefinition def)
{ {
definition = def; definition = def;
//schema 2020/06 id is now name; name is now label //schema 2020/06 id is now name; name is now label
name = attr.getAttribute("name"); name = attr.getAttribute("name");
label = name; //set label to name if not specified label = name; //set label to name if not specified
as = As.Unsigned; //default value as = As.Unsigned; //default value
syntax = TokenDefinition.Syntax.DirectoryString; //default value //TODO xpath would be better
String ASNSyntax = attr.getElementsByTagName("ts:type").item(0).getTextContent();
if(ASNSyntax != null) {
syntax = getSyntax(ASNSyntax);
} else {
syntax = TokenDefinition.Syntax.DirectoryString; // 1.3.6.1.4.1.1466.115.121.1.15
}
for(Node node = attr.getFirstChild(); for(Node node = attr.getFirstChild();
node!=null; node=node.getNextSibling()){ node!=null; node=node.getNextSibling()){

@ -8,9 +8,9 @@ import java.math.BigInteger;
*/ */
public interface AttributeInterface public interface AttributeInterface
{ {
TransactionResult getFunctionResult(ContractAddress contract, AttributeType attr, BigInteger tokenId); TransactionResult getFunctionResult(ContractAddress contract, Attribute attr, BigInteger tokenId);
TransactionResult storeAuxData(TransactionResult tResult); TransactionResult storeAuxData(TransactionResult tResult);
boolean resolveOptimisedAttr(ContractAddress contract, AttributeType attr, TransactionResult transactionResult); boolean resolveOptimisedAttr(ContractAddress contract, Attribute attr, TransactionResult transactionResult);
String getWalletAddr(); String getWalletAddr();

@ -14,6 +14,6 @@ public class TSAction
public String style = ""; public String style = "";
public String name; public String name;
public Map<String, AttributeType> attributeTypes; public Map<String, Attribute> attributeTypes;
public FunctionDefinition function; public FunctionDefinition function;
} }

@ -8,7 +8,7 @@ import java.util.Map;
*/ */
public class TSTokenViewHolder public class TSTokenViewHolder
{ {
public Map<String, AttributeType> localAttributeTypes = new HashMap<>(); public Map<String, Attribute> localAttributeTypes = new HashMap<>();
public Map<String, TSTokenView> views = new HashMap<>(); public Map<String, TSTokenView> views = new HashMap<>();
public String globalStyle = ""; public String globalStyle = "";

@ -16,7 +16,7 @@ public class TransactionResult
public long resultTime; public long resultTime;
public final String attrId; public final String attrId;
public TransactionResult(int chainId, String address, BigInteger tokenId, AttributeType attr) public TransactionResult(int chainId, String address, BigInteger tokenId, Attribute attr)
{ {
this.contractAddress = address; this.contractAddress = address;
this.contractChainId = chainId; this.contractChainId = chainId;

@ -20,7 +20,7 @@ import static org.w3c.dom.Node.ELEMENT_NODE;
public class TokenDefinition { public class TokenDefinition {
protected Document xml; protected Document xml;
public Map<String, AttributeType> attributeTypes = new HashMap<>(); public Map<String, Attribute> attributes = new HashMap<>();
protected Locale locale; protected Locale locale;
public Map<String, ContractInfo> contracts = new HashMap<>(); public Map<String, ContractInfo> contracts = new HashMap<>();
@ -69,7 +69,7 @@ public class TokenDefinition {
public List<FunctionDefinition> getFunctionData() public List<FunctionDefinition> getFunctionData()
{ {
List<FunctionDefinition> defs = new ArrayList<>(); List<FunctionDefinition> defs = new ArrayList<>();
for (AttributeType attr : attributeTypes.values()) for (Attribute attr : attributes.values())
{ {
if (attr.function != null) if (attr.function != null)
{ {
@ -345,7 +345,7 @@ public class TokenDefinition {
case "cards": case "cards":
handleCards(element); handleCards(element);
break; break;
case "attribute": //treat orphaned attribute-types appearing on the root scope as globals case "attribute":
processAttrs(element); processAttrs(element);
break; break;
default: default:
@ -434,8 +434,8 @@ public class TokenDefinition {
Element element = (Element) node; Element element = (Element) node;
switch (node.getLocalName()) switch (node.getLocalName())
{ {
case "attribute-type": case "attribute":
AttributeType attr = new AttributeType(element, this); Attribute attr = new Attribute(element, this);
tokenViews.localAttributeTypes.put(attr.name, attr); tokenViews.localAttributeTypes.put(attr.name, attr);
break; break;
case "view": //TODO: Localisation case "view": //TODO: Localisation
@ -577,8 +577,7 @@ public class TokenDefinition {
tsAction.name = getLocalisedString(element); tsAction.name = getLocalisedString(element);
break; break;
case "attribute": case "attribute":
case "attribute-type": Attribute attr = new Attribute(element, this);
AttributeType attr = new AttributeType(element, this);
if (tsAction.attributeTypes == null) if (tsAction.attributeTypes == null)
tsAction.attributeTypes = new HashMap<>(); tsAction.attributeTypes = new HashMap<>();
tsAction.attributeTypes.put(attr.name, attr); tsAction.attributeTypes.put(attr.name, attr);
@ -680,10 +679,10 @@ public class TokenDefinition {
private void processAttrs(Node n) private void processAttrs(Node n)
{ {
AttributeType attr = new AttributeType((Element) n, this); Attribute attr = new Attribute((Element) n, this);
if (attr.bitmask != null || attr.function != null) if (attr.bitmask != null || attr.function != null)
{ {
attributeTypes.put(attr.name, attr); attributes.put(attr.name, attr);
} }
} }
@ -726,16 +725,16 @@ public class TokenDefinition {
} }
public Map<BigInteger, String> getMappingMembersByKey(String key){ public Map<BigInteger, String> getMappingMembersByKey(String key){
if(attributeTypes.containsKey(key)) { if(attributes.containsKey(key)) {
AttributeType attr = attributeTypes.get(key); Attribute attr = attributes.get(key);
return attr.members; return attr.members;
} }
return null; return null;
} }
public Map<BigInteger, String> getConvertedMappingMembersByKey(String key){ public Map<BigInteger, String> getConvertedMappingMembersByKey(String key){
if(attributeTypes.containsKey(key)) { if(attributes.containsKey(key)) {
Map<BigInteger,String> convertedMembers=new HashMap<>(); Map<BigInteger,String> convertedMembers=new HashMap<>();
AttributeType attr = attributeTypes.get(key); Attribute attr = attributes.get(key);
for(BigInteger actualValue:attr.members.keySet()){ for(BigInteger actualValue:attr.members.keySet()){
convertedMembers.put(actualValue.shiftLeft(attr.bitshift).and(attr.bitmask),attr.members.get(actualValue)); convertedMembers.put(actualValue.shiftLeft(attr.bitshift).and(attr.bitmask),attr.members.get(actualValue));
} }
@ -982,8 +981,8 @@ public class TokenDefinition {
} }
public void parseField(BigInteger tokenId, NonFungibleToken token, Map<String, FunctionDefinition> functionMappings) { public void parseField(BigInteger tokenId, NonFungibleToken token, Map<String, FunctionDefinition> functionMappings) {
for (String key : attributeTypes.keySet()) { for (String key : attributes.keySet()) {
AttributeType attrtype = attributeTypes.get(key); Attribute attrtype = attributes.get(key);
BigInteger val = BigInteger.ZERO; BigInteger val = BigInteger.ZERO;
try try
{ {
@ -1064,8 +1063,8 @@ public class TokenDefinition {
} }
public void parseField(BigInteger tokenId, NonFungibleToken token) { public void parseField(BigInteger tokenId, NonFungibleToken token) {
for (String key : attributeTypes.keySet()) { for (String key : attributes.keySet()) {
AttributeType attrtype = attributeTypes.get(key); Attribute attrtype = attributes.get(key);
BigInteger val = BigInteger.ZERO; BigInteger val = BigInteger.ZERO;
try try
{ {
@ -1120,7 +1119,7 @@ public class TokenDefinition {
return tokenViews.getViewStyle(viewTag); return tokenViews.getViewStyle(viewTag);
} }
public Map<String, AttributeType> getTokenViewLocalAttributes() public Map<String, Attribute> getTokenViewLocalAttributes()
{ {
return tokenViews.localAttributeTypes; return tokenViews.localAttributeTypes;
} }

@ -24,7 +24,7 @@ public class TokenDefinitionTest implements ParseResult
public void TokenInformationCanBeExtracted() throws IOException, SAXException { public void TokenInformationCanBeExtracted() throws IOException, SAXException {
assertTrue(entryTokenTestFile.exists()); assertTrue(entryTokenTestFile.exists());
TokenDefinition entryToken = new TokenDefinition(new FileInputStream(entryTokenTestFile), new Locale("en"), this); TokenDefinition entryToken = new TokenDefinition(new FileInputStream(entryTokenTestFile), new Locale("en"), this);
assertFalse(entryToken.attributeTypes.isEmpty()); assertFalse(entryToken.attributes.isEmpty());
for (String contractName : entryToken.contracts.keySet()) for (String contractName : entryToken.contracts.keySet())
{ {
assertNotEquals(0, contractName.length()); assertNotEquals(0, contractName.length());

@ -424,7 +424,8 @@
</ts:view> </ts:view>
</ts:card> </ts:card>
</ts:cards> </ts:cards>
<ts:attribute-type name="locality" syntax="1.3.6.1.4.1.1466.115.121.1.15"> <ts:attribute name="locality">
<ts:type><ts:syntax>1.3.6.1.4.1.1466.115.121.1.15</ts:syntax></ts:type>
<ts:origins> <ts:origins>
<ethereum:call as="utf8" contract="EntryToken" function="getLocality"> <ethereum:call as="utf8" contract="EntryToken" function="getLocality">
<ts:data> <ts:data>
@ -433,8 +434,9 @@
</ethereum:call> </ethereum:call>
</ts:origins> </ts:origins>
</ts:attribute-type> </ts:attribute>
<ts:attribute-type name="time" syntax="1.3.6.1.4.1.1466.115.121.1.24"> <ts:attribute name="time">
<ts:type><ts:syntax>1.3.6.1.4.1.1466.115.121.1.24</ts:syntax></ts:type>
<ts:label> <ts:label>
<ts:string xml:lang="en">Time</ts:string> <ts:string xml:lang="en">Time</ts:string>
<ts:string xml:lang="zh">时间</ts:string> <ts:string xml:lang="zh">时间</ts:string>
@ -442,8 +444,9 @@
<ts:origins> <ts:origins>
<ts:token-id as="utf8" bitmask="0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000000000"></ts:token-id> <ts:token-id as="utf8" bitmask="0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000000000"></ts:token-id>
</ts:origins> </ts:origins>
</ts:attribute-type> </ts:attribute>
<ts:attribute-type name="expired" syntax="1.3.6.1.4.1.1466.115.121.1.7"> <!-- boolean --> <ts:attribute name="expired"> <!-- boolean -->
<ts:type><ts:syntax>1.3.6.1.4.1.1466.115.121.1.7</ts:syntax></ts:type>
<ts:origins> <ts:origins>
<ethereum:call as="bool" contract="EntryToken" function="isExpired"> <ethereum:call as="bool" contract="EntryToken" function="isExpired">
<ts:data> <ts:data>
@ -451,8 +454,9 @@
</ts:data> </ts:data>
</ethereum:call> </ethereum:call>
</ts:origins> </ts:origins>
</ts:attribute-type> </ts:attribute>
<ts:attribute-type name="street" syntax="1.3.6.1.4.1.1466.115.121.1.15"> <!-- string --> <ts:attribute name="street"> <!-- string -->
<ts:type><ts:syntax>1.3.6.1.4.1.1466.115.121.1.15</ts:syntax></ts:type>
<ts:origins> <ts:origins>
<ethereum:call as="utf8" contract="EntryToken" function="getStreet"> <ethereum:call as="utf8" contract="EntryToken" function="getStreet">
<ts:data> <ts:data>
@ -460,8 +464,9 @@
</ts:data> </ts:data>
</ethereum:call> </ethereum:call>
</ts:origins> </ts:origins>
</ts:attribute-type> </ts:attribute>
<ts:attribute-type name="building" syntax="1.3.6.1.4.1.1466.115.121.1.15"> <!-- string --> <ts:attribute name="building"> <!-- string -->
<ts:type><ts:syntax>1.3.6.1.4.1.1466.115.121.1.15</ts:syntax></ts:type>
<ts:origins> <ts:origins>
<ethereum:call as="utf8" contract="EntryToken" function="getBuildingName"> <ethereum:call as="utf8" contract="EntryToken" function="getBuildingName">
<ts:data> <ts:data>
@ -469,8 +474,9 @@
</ts:data> </ts:data>
</ethereum:call> </ethereum:call>
</ts:origins> </ts:origins>
</ts:attribute-type> </ts:attribute>
<ts:attribute-type name="state" syntax="1.3.6.1.4.1.1466.115.121.1.15"> <!-- string --> <ts:attribute name="state"> <!-- string -->
<ts:type><ts:syntax>1.3.6.1.4.1.1466.115.121.1.15</ts:syntax></ts:type>
<ts:origins> <ts:origins>
<ethereum:call as="utf8" contract="EntryToken" function="getState"> <ethereum:call as="utf8" contract="EntryToken" function="getState">
<ts:data> <ts:data>
@ -478,5 +484,5 @@
</ts:data> </ts:data>
</ethereum:call> </ethereum:call>
</ts:origins> </ts:origins>
</ts:attribute-type> </ts:attribute>
</ts:token> </ts:token>

@ -9,7 +9,6 @@ import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.FunctionReturnDecoder; import org.web3j.abi.FunctionReturnDecoder;
import org.web3j.abi.TypeReference; import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Address; import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.BytesType;
import org.web3j.abi.datatypes.Function; import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Int; import org.web3j.abi.datatypes.Int;
import org.web3j.abi.datatypes.Type; import org.web3j.abi.datatypes.Type;
@ -556,7 +555,7 @@ public abstract class TokenscriptFunction
return name; return name;
} }
public TokenScriptResult.Attribute parseFunctionResult(TransactionResult transactionResult, AttributeType attr) public TokenScriptResult.Attribute parseFunctionResult(TransactionResult transactionResult, Attribute attr)
{ {
String res = attr.getSyntaxVal(transactionResult.result); String res = attr.getSyntaxVal(transactionResult.result);
BigInteger val = transactionResult.tokenId; //? BigInteger val = transactionResult.tokenId; //?
@ -586,7 +585,7 @@ public abstract class TokenscriptFunction
* @param definition * @param definition
* @return * @return
*/ */
public Observable<TransactionResult> fetchResultFromEthereum(String walletAddress, ContractAddress override, AttributeType attr, BigInteger tokenId, TokenDefinition definition, AttributeInterface attrIf) public Observable<TransactionResult> fetchResultFromEthereum(String walletAddress, ContractAddress override, Attribute attr, BigInteger tokenId, TokenDefinition definition, AttributeInterface attrIf)
{ {
return Observable.fromCallable(() -> { return Observable.fromCallable(() -> {
ContractAddress useAddress; ContractAddress useAddress;
@ -650,13 +649,13 @@ public abstract class TokenscriptFunction
private void resolveReference(String walletAddress, MethodArg arg, BigInteger tokenId, TokenDefinition definition, AttributeInterface attrIf) private void resolveReference(String walletAddress, MethodArg arg, BigInteger tokenId, TokenDefinition definition, AttributeInterface attrIf)
{ {
if (definition != null && definition.attributeTypes.containsKey(arg.element.ref)) if (definition != null && definition.attributes.containsKey(arg.element.ref))
{ {
arg.element.value = fetchAttrResult(walletAddress, definition.attributeTypes.get(arg.element.ref), tokenId, null, definition, attrIf).blockingSingle().text; arg.element.value = fetchAttrResult(walletAddress, definition.attributes.get(arg.element.ref), tokenId, null, definition, attrIf).blockingSingle().text;
} }
} }
public Observable<TokenScriptResult.Attribute> fetchAttrResult(String walletAddress, AttributeType attr, BigInteger tokenId, ContractAddress cAddr, TokenDefinition td, AttributeInterface attrIf) public Observable<TokenScriptResult.Attribute> fetchAttrResult(String walletAddress, Attribute attr, BigInteger tokenId, ContractAddress cAddr, TokenDefinition td, AttributeInterface attrIf)
{ {
if (attr == null) return Observable.fromCallable(() -> null); if (attr == null) return Observable.fromCallable(() -> null);
if (attr.function == null) // static attribute from tokenId (eg city mapping from tokenId) if (attr.function == null) // static attribute from tokenId (eg city mapping from tokenId)
@ -690,11 +689,11 @@ public abstract class TokenscriptFunction
td.context.cAddr = cAddr; td.context.cAddr = cAddr;
td.context.attrInterface = attrIf; td.context.attrInterface = attrIf;
return Observable.fromIterable(new ArrayList<>(td.attributeTypes.values())) return Observable.fromIterable(new ArrayList<>(td.attributes.values()))
.flatMap(attr -> fetchAttrResult(walletAddress, attr, tokenId, cAddr, td, attrIf)); .flatMap(attr -> fetchAttrResult(walletAddress, attr, tokenId, cAddr, td, attrIf));
} }
private Observable<TokenScriptResult.Attribute> staticAttribute(AttributeType attr, BigInteger tokenId) private Observable<TokenScriptResult.Attribute> staticAttribute(Attribute attr, BigInteger tokenId)
{ {
return Observable.fromCallable(() -> { return Observable.fromCallable(() -> {
try try
@ -709,7 +708,7 @@ public abstract class TokenscriptFunction
}); });
} }
private Observable<TokenScriptResult.Attribute> resultFromDatabase(TransactionResult transactionResult, AttributeType attr) private Observable<TokenScriptResult.Attribute> resultFromDatabase(TransactionResult transactionResult, Attribute attr)
{ {
//return Observable.fromCallable(() -> attr.function.parseFunctionResult(transactionResult, attr)); //return Observable.fromCallable(() -> attr.function.parseFunctionResult(transactionResult, attr));
return Observable.fromCallable(() -> parseFunctionResult(transactionResult, attr)); return Observable.fromCallable(() -> parseFunctionResult(transactionResult, attr));

@ -4,8 +4,8 @@ import com.alphawallet.scripttool.Entity.CachedResult;
import com.alphawallet.scripttool.Entity.ParseState; import com.alphawallet.scripttool.Entity.ParseState;
import com.alphawallet.scripttool.Entity.TokenscriptFunction; import com.alphawallet.scripttool.Entity.TokenscriptFunction;
import com.alphawallet.scripttool.Ethereum.TransactionHandler; import com.alphawallet.scripttool.Ethereum.TransactionHandler;
import com.alphawallet.token.entity.Attribute;
import com.alphawallet.token.entity.AttributeInterface; import com.alphawallet.token.entity.AttributeInterface;
import com.alphawallet.token.entity.AttributeType;
import com.alphawallet.token.entity.ContractAddress; import com.alphawallet.token.entity.ContractAddress;
import com.alphawallet.token.entity.ContractInfo; import com.alphawallet.token.entity.ContractInfo;
import com.alphawallet.token.entity.TSAction; import com.alphawallet.token.entity.TSAction;
@ -230,7 +230,7 @@ public class ScriptTool implements AttributeInterface
} }
@Override @Override
public TransactionResult getFunctionResult(ContractAddress contract, AttributeType attr, public TransactionResult getFunctionResult(ContractAddress contract, Attribute attr,
BigInteger tokenId) BigInteger tokenId)
{ {
String addressFunctionKey = contract.address + "-" + attr.name; String addressFunctionKey = contract.address + "-" + attr.name;
@ -263,7 +263,7 @@ public class ScriptTool implements AttributeInterface
} }
@Override @Override
public boolean resolveOptimisedAttr(ContractAddress contract, AttributeType attr, public boolean resolveOptimisedAttr(ContractAddress contract, Attribute attr,
TransactionResult transactionResult) TransactionResult transactionResult)
{ {
return false; return false;

Loading…
Cancel
Save