2
2
3
3
import static com .alphawallet .app .repository .TokenRepository .getWeb3jService ;
4
4
import static com .alphawallet .app .repository .TokensRealmSource .IMAGES_DB ;
5
+ import static com .alphawallet .ethereum .EthereumNetworkBase .MAINNET_ID ;
6
+ import static com .alphawallet .token .tools .TokenDefinition .TOKENSCRIPT_ADDRESS ;
7
+ import static com .alphawallet .token .tools .TokenDefinition .TOKENSCRIPT_CHAIN ;
5
8
import static com .alphawallet .token .tools .TokenDefinition .TOKENSCRIPT_CURRENT_SCHEMA ;
6
9
import static com .alphawallet .token .tools .TokenDefinition .TOKENSCRIPT_REPO_SERVER ;
10
+ import static com .alphawallet .token .tools .TokenDefinition .TOKENSCRIPT_STORE_SERVER ;
7
11
import static com .alphawallet .token .tools .TokenDefinition .UNCHANGED_SCRIPT ;
8
12
9
13
import android .Manifest ;
67
71
import com .alphawallet .token .tools .TokenDefinition ;
68
72
69
73
import org .jetbrains .annotations .NotNull ;
74
+ import org .json .JSONArray ;
75
+ import org .json .JSONObject ;
70
76
import org .web3j .abi .DefaultFunctionEncoder ;
71
77
import org .web3j .abi .FunctionEncoder ;
72
78
import org .web3j .abi .datatypes .Function ;
@@ -385,9 +391,10 @@ private void handleFileLoadError(Throwable throwable, File file)
385
391
386
392
private TokenDefinition fileLoadComplete (List <ContractLocator > originContracts , TokenScriptFile file , TokenDefinition td )
387
393
{
388
- if (originContracts .size () == 0 || td .getAttestation () != null ) return td ; //no action needed, not accessible to Attestation //TODO: Refactor once we handle multiple attestations
394
+ if (originContracts .isEmpty () || td .getAttestation () != null ) return td ; //no action needed, not accessible to Attestation //TODO: Refactor once we handle multiple attestations
389
395
390
396
boolean hasEvents = td .hasEvents ();
397
+ long primaryChainId = !originContracts .isEmpty () ? originContracts .iterator ().next ().chainId : MAINNET_ID ;
391
398
392
399
try (Realm realm = realmManager .getRealmInstance (ASSET_DEFINITION_DB ))
393
400
{
@@ -396,7 +403,7 @@ private TokenDefinition fileLoadComplete(List<ContractLocator> originContracts,
396
403
{
397
404
//delete this file and check downloads for update
398
405
removeFile (file .getAbsolutePath ());
399
- loadScriptFromServer (getFileName (file ));
406
+ loadScriptFromServer (primaryChainId , getFileName (file ));
400
407
return td ;
401
408
}
402
409
@@ -1011,7 +1018,7 @@ private TokenScriptFile locateTokenScriptFile(String fileName)
1011
1018
* Get asset definition given contract address
1012
1019
*
1013
1020
* @param address
1014
- * @return
1021
+ * @return The Token Definition for the given chain, address
1015
1022
*/
1016
1023
public TokenDefinition getAssetDefinition (long chainId , String address )
1017
1024
{
@@ -1026,7 +1033,7 @@ public TokenDefinition getAssetDefinition(long chainId, String address)
1026
1033
if (assetDef == null && !address .equals ("ethereum" ))
1027
1034
{
1028
1035
//try web
1029
- loadScriptFromServer (address .toLowerCase ()); //this will complete asynchronously and display will be updated
1036
+ loadScriptFromServer (chainId , address .toLowerCase ()); //this will complete asynchronously and display will be updated
1030
1037
}
1031
1038
1032
1039
return assetDef ; // if nothing found use default
@@ -1066,10 +1073,10 @@ public Single<TokenDefinition> getAssetDefinitionASync(long chainId, String addr
1066
1073
}
1067
1074
1068
1075
String convertedAddr = (address .equalsIgnoreCase (tokensService .getCurrentAddress ())) ? "ethereum" : address .toLowerCase ();
1069
- return getAssetDefinitionASync (getDefinition (getTSDataKey (chainId , address )), convertedAddr );
1076
+ return getAssetDefinitionASync (getDefinition (getTSDataKey (chainId , address )), chainId , convertedAddr );
1070
1077
}
1071
1078
1072
- private Single <TokenDefinition > getAssetDefinitionASync (final TokenDefinition assetDef , final String contractName )
1079
+ private Single <TokenDefinition > getAssetDefinitionASync (final TokenDefinition assetDef , final long chainId , final String contractName )
1073
1080
{
1074
1081
if (assetDef != null )
1075
1082
{
@@ -1078,7 +1085,7 @@ private Single<TokenDefinition> getAssetDefinitionASync(final TokenDefinition as
1078
1085
else if (!contractName .equals ("ethereum" ))
1079
1086
{
1080
1087
//at this stage, this script isn't replacing any existing script, so it's safe to write to database without checking if we need to delete anything
1081
- return fetchXMLFromServer (contractName .toLowerCase ())
1088
+ return fetchXMLFromServer (chainId , contractName .toLowerCase ())
1082
1089
.flatMap (this ::handleNewTSFile );
1083
1090
}
1084
1091
else return Single .fromCallable (TokenDefinition ::new );
@@ -1095,7 +1102,7 @@ public Single<TokenDefinition> getAssetDefinitionASync(Token token)
1095
1102
// hold until asset definitions have finished loading
1096
1103
waitForAssets ();
1097
1104
1098
- return getAssetDefinitionASync (getDefinition (token .getTSKey ()), contractName );
1105
+ return getAssetDefinitionASync (getDefinition (token .getTSKey ()), token . tokenInfo . chainId , contractName );
1099
1106
}
1100
1107
1101
1108
private void waitForAssets ()
@@ -1169,12 +1176,12 @@ public String getIssuerName(Token token)
1169
1176
return issuer ;
1170
1177
}
1171
1178
1172
- private void loadScriptFromServer (String correctedAddress )
1179
+ private void loadScriptFromServer (long chainId , String correctedAddress )
1173
1180
{
1174
1181
//first check the last time we tried this session
1175
1182
if (assetChecked .get (correctedAddress ) == null || (System .currentTimeMillis () > (assetChecked .get (correctedAddress ) + 1000L * 60L * 60L )))
1176
1183
{
1177
- fetchXMLFromServer (correctedAddress )
1184
+ fetchXMLFromServer (chainId , correctedAddress )
1178
1185
.flatMap (this ::handleNewTSFile )
1179
1186
.subscribeOn (Schedulers .io ())
1180
1187
.observeOn (AndroidSchedulers .mainThread ())
@@ -1416,23 +1423,23 @@ private boolean matchesExistingScript(Token token, String uri)
1416
1423
return false ;
1417
1424
}
1418
1425
1419
- private Single <File > tryServerIfRequired (File contractScript , String address )
1426
+ private Single <File > tryServerIfRequired (File contractScript , String address , long chainId )
1420
1427
{
1421
1428
if (contractScript .exists () || contractScript .getName ().equals (UNCHANGED_SCRIPT ))
1422
1429
{
1423
1430
return Single .fromCallable (() -> contractScript );
1424
1431
}
1425
1432
else
1426
1433
{
1427
- return fetchXMLFromServer (address );
1434
+ return fetchXMLFromServer (chainId , address );
1428
1435
}
1429
1436
}
1430
1437
1431
- private Single <File > fetchXMLFromServer (String address )
1438
+ private Single <File > fetchXMLFromServer (long chainId , String address )
1432
1439
{
1433
1440
return Single .fromCallable (() -> {
1434
1441
final File defaultReturn = new File ("" );
1435
- if (address .equals ( "" )) return defaultReturn ;
1442
+ if (address .isEmpty ( )) return defaultReturn ;
1436
1443
1437
1444
File result = getDownloadedXMLFile (address );
1438
1445
@@ -1459,15 +1466,19 @@ private Single<File> fetchXMLFromServer(String address)
1459
1466
if (assetChecked .get (address ) != null && (System .currentTimeMillis () > (assetChecked .get (address ) + 1000L * 60L * 60L )))
1460
1467
return result ;
1461
1468
1462
- String sb = TOKENSCRIPT_REPO_SERVER +
1463
- TOKENSCRIPT_CURRENT_SCHEMA +
1464
- "/" +
1465
- address ;
1469
+ //use the updated server
1470
+ String sb = TOKENSCRIPT_STORE_SERVER .replace (TOKENSCRIPT_ADDRESS , address ).replace (TOKENSCRIPT_CHAIN , Long .toString (chainId ));
1466
1471
1467
1472
Pair <String , Boolean > downloadResponse = downloadScript (sb , fileTime );
1468
- if (!TextUtils .isEmpty (downloadResponse .first ))
1473
+ String offchainScriptUri = getOffchainScriptUri (downloadResponse );
1474
+
1475
+ if (!TextUtils .isEmpty (offchainScriptUri ))
1469
1476
{
1470
- result = storeFile (address , downloadResponse );
1477
+ downloadResponse = downloadScript (offchainScriptUri , fileTime );
1478
+ if (!TextUtils .isEmpty (downloadResponse .first ))
1479
+ {
1480
+ storeFile (address , downloadResponse );
1481
+ }
1471
1482
}
1472
1483
1473
1484
assetChecked .put (address , System .currentTimeMillis ());
@@ -1476,6 +1487,27 @@ private Single<File> fetchXMLFromServer(String address)
1476
1487
});
1477
1488
}
1478
1489
1490
+ private String getOffchainScriptUri (Pair <String , Boolean > downloadResponse )
1491
+ {
1492
+ String offchainScriptResponse = "" ;
1493
+ try
1494
+ {
1495
+ JSONObject response = new JSONObject (downloadResponse .first );
1496
+ JSONObject scriptUri = response .getJSONObject ("scriptURI" );
1497
+ JSONArray offchainLinks = scriptUri .getJSONArray ("offchain" );
1498
+ if (offchainLinks .length () > 0 )
1499
+ {
1500
+ offchainScriptResponse = offchainLinks .getString (0 );
1501
+ }
1502
+ }
1503
+ catch (Exception e )
1504
+ {
1505
+ offchainScriptResponse = "" ;
1506
+ }
1507
+
1508
+ return offchainScriptResponse ;
1509
+ }
1510
+
1479
1511
private Pair <String , Boolean > downloadScript (String Uri , long currentFileTime )
1480
1512
{
1481
1513
if (Uri .equals (UNCHANGED_SCRIPT ))
@@ -3116,7 +3148,7 @@ public Single<TokenDefinition> checkServerForScript(Token token, MutableLiveData
3116
3148
3117
3149
//try the contractURI, then server
3118
3150
return fetchTokenScriptFromContract (token , updateFlag )
3119
- .flatMap (file -> tryServerIfRequired (file , token .getAddress ().toLowerCase ()))
3151
+ .flatMap (file -> tryServerIfRequired (file , token .getAddress ().toLowerCase (), token . tokenInfo . chainId ))
3120
3152
.flatMap (this ::handleNewTSFile )
3121
3153
.subscribeOn (Schedulers .io ())
3122
3154
.observeOn (AndroidSchedulers .mainThread ());
0 commit comments